Skip to content

Commit

Permalink
Merge pull request #1442 from mrvisscher/major-functionality
Browse files Browse the repository at this point in the history
Major functionality
  • Loading branch information
mrvisscher authored Feb 3, 2025
2 parents bdad001 + 3e92fa2 commit 1d34603
Show file tree
Hide file tree
Showing 104 changed files with 3,843 additions and 1,462 deletions.
1 change: 1 addition & 0 deletions .github/conda-envs/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: test
channels:
- conda-forge
- cmutel
- mrvisscher
dependencies:
- pytest
- pytest-qt
Expand Down
4 changes: 2 additions & 2 deletions .github/dev-recipe/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# conda recipe for activity-browser-dev
# https://anaconda.org/bsteubing/activity-browser-dev
package:
name: "{{ os.environ.get('PKG_NAME', 'activity-browser-dev25') }}"
version: "{{ os.environ.get('VERSION', 'dev') }}"
name: "{{ os.environ.get('PKG_NAME', 'activity-browser-beta') }}"
version: "{{ os.environ.get('VERSION', 'beta') }}"

source:
path: ../..
Expand Down
54 changes: 47 additions & 7 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: conda - tests and development release
name: tests and development release
on:
pull_request:
branches:
- main
- minor
- brightway25
- major
push:
branches:
- main
- brightway25
- major

jobs:
patch-test-environment:
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
micromamba env export
micromamba env export > env.yaml
- name: Upload final environment as artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: env-${{ matrix.os }}-${{ matrix.python-version }}
path: env.yaml
Expand Down Expand Up @@ -105,13 +105,13 @@ jobs:
needs:
- tests
# And only on a push event, not a pull_request.
if: ${{ github.event_name == 'push' }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}
env:
PKG_NAME: "activity-browser-dev25"
PKG_NAME: "activity-browser-dev"
steps:
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -139,4 +139,44 @@ jobs:
- name: Upload the activity-browser-dev package
run: |
anaconda -t ${{ secrets.CONDA_UPLOAD_TOKEN }} upload \
/usr/share/miniconda/envs/build/conda-bld/noarch/*.tar.bz2
/usr/share/miniconda/envs/build/conda-bld/noarch/*.conda
deploy-beta:
# And only on a push event, not a pull_request.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/major' }}
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}
env:
PKG_NAME: "activity-browser-beta"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: "0"
- name: Build and deploy 3.11
uses: conda-incubator/setup-miniconda@v2
with:
python-version: 3.11
activate-environment: build
environment-file: .github/conda-envs/build.yml
- name: Export version
run: |
ID=$(git rev-list 2.11.0..HEAD --count)
VERSION="3.b.${ID}"
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Patch recipe with run requirements from stable
uses: mikefarah/yq@master
# Adds the run dependencies from the stable recipe to the dev recipe (inplace)
with:
cmd: |
yq eval-all -i 'select(fi == 0).requirements.run += select(fi == 1).requirements.run | select(fi == 0)' .github/dev-recipe/meta.yaml recipe/meta.yaml
- name: Show patched dev recipe
run: cat .github/dev-recipe/meta.yaml
- name: Build beta package
run: |
conda build .github/dev-recipe/
- name: Upload the activity-browser-dev package
run: |
anaconda -t ${{ secrets.CONDA_MRVISSCHER }} upload \
/usr/share/miniconda/envs/build/conda-bld/noarch/*.conda
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ jobs:
- name: Upload to anaconda.org
run: |
anaconda -t ${{ secrets.CONDA_UPLOAD_TOKEN }} upload \
/usr/share/miniconda/envs/build/conda-bld/noarch/*.tar.bz2
/usr/share/miniconda/envs/build/conda-bld/noarch/*.conda
- name: Update wiki
run: ./.github/scripts/update_wiki.sh "Automated documentation update for $GITHUB_REF_NAME" "${{ secrets.GITHUB_TOKEN }}"
13 changes: 11 additions & 2 deletions activity_browser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,17 @@
def load_settings() -> None:
if ab_settings.settings:
from pathlib import Path
bw2data.projects.change_base_directories(Path(ab_settings.current_bw_dir))
bw2data.projects.set_current(ab_settings.startup_project)

base_dir = Path(ab_settings.current_bw_dir)
project_name = ab_settings.startup_project

bw2data.projects.change_base_directories(base_dir, project_name=project_name, update=False)

if not bw2data.projects.twofive:
from .actions import ProjectSwitch
log.warning(f"Project: {bw2data.projects.current} is not yet BW25 compatible")
ProjectSwitch.set_warning_bar()

log.info(f"Brightway2 data directory: {bw2data.projects._base_data_dir}")
log.info(f"Brightway2 current project: {bw2data.projects.current}")

Expand Down
14 changes: 13 additions & 1 deletion activity_browser/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
from .activity.activity_open import ActivityOpen
from .activity.activity_relink import ActivityRelink
from .activity.node_properties import NodeProperties
from .biosphere_update import BiosphereUpdate
from .activity.activity_redo_allocation import MultifunctionalProcessRedoAllocation
from .activity.process_default_property_modify import ProcessDefaultPropertyModify
from .activity.process_default_property_remove import ProcessDefaultPropertyRemove
from .activity.function_substitute import FunctionSubstitute
from .activity.function_substitute_remove import FunctionSubstituteRemove

from .calculation_setup.cs_new import CSNew
from .calculation_setup.cs_delete import CSDelete
Expand All @@ -25,6 +29,10 @@
from .database.database_duplicate import DatabaseDuplicate
from .database.database_relink import DatabaseRelink
from .database.database_redo_allocation import DatabaseRedoAllocation
from .database.database_explorer_open import DatabaseExplorerOpen
from .database.database_process import DatabaseProcess

from .biosphere_update import BiosphereUpdate
from .default_install import DefaultInstall
from .exchange.exchange_copy_sdf import ExchangeCopySDF

Expand Down Expand Up @@ -67,6 +75,10 @@
from .project.project_switch import ProjectSwitch
from .project.project_export import ProjectExport
from .project.project_import import ProjectImport
from .project.project_manager_open import ProjectManagerOpen
from .project.project_migrate25 import ProjectMigrate25
from .project.project_create_template import ProjectCreateTemplate
from .project.project_new_template import ProjectNewFromTemplate

from .default_install import DefaultInstall
from .biosphere_update import BiosphereUpdate
Expand Down
14 changes: 7 additions & 7 deletions activity_browser/actions/activity/activity_modify.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from typing import Callable, Union

from qtpy import QtCore

from activity_browser.actions.base import ABAction, exception_dialogs
from bw2data import get_activity
from bw2data import get_node, Node
from activity_browser.ui.icons import qicons
from activity_browser import bwutils

from .activity_redo_allocation import MultifunctionalProcessRedoAllocation


class ActivityModify(ABAction):
Expand All @@ -19,7 +18,8 @@ class ActivityModify(ABAction):

@staticmethod
@exception_dialogs
def run(activity_key: tuple, field: str, value: any):
activity = get_activity(activity_key)
def run(activity: tuple | int | Node, field: str, value: any):
activity = bwutils.refresh_node(activity)

activity[field] = value
activity.save()
14 changes: 2 additions & 12 deletions activity_browser/actions/activity/activity_new_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,7 @@ def run(database_name: str):
"location": location,
"type": "product",
}
database = Database(database_name)
new_ref_prod = database.new_activity(code=uuid4().hex, **new_ref_prod_data)
new_ref_prod.save()

# create new exchange
new_exchange = new_process.new_edge(
input=new_ref_prod,
type=labels.production_edge_default,
amount=1,
functional=True
)
new_exchange.save()
prod = new_process.new_product(code=uuid4().hex, **new_ref_prod_data)
prod.save()

ActivityOpen.run([new_process.key])
23 changes: 8 additions & 15 deletions activity_browser/actions/activity/activity_new_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

from qtpy.QtWidgets import QDialog

from bw2data import Database, get_activity, labels

from bw_functional import Process

from activity_browser import application
from activity_browser.actions.base import ABAction, exception_dialogs
from bw2data import Database, get_activity, labels
from activity_browser.ui.icons import qicons
from activity_browser.ui.widgets.new_node_dialog import NewNodeDialog

Expand Down Expand Up @@ -33,25 +36,15 @@ def run(process_key: tuple):
if not name:
return

process = get_activity(key=process_key)
assert isinstance(process, Process), "Cannot create new product for non-process type"

# create product
new_prod_data = {
"name": name,
"unit": unit,
"location": location,
"type": "product",
}
database = Database(process_key[0])
new_product = database.new_activity(code=uuid4().hex, **new_prod_data)
new_product = process.new_product(code=uuid4().hex, **new_prod_data)
new_product.save()

process = get_activity(process_key)

new_exchange = process.new_edge(
input=new_product,
type=labels.production_edge_default,
amount=1,
functional=True
)
new_exchange.save()

ActivityOpen.run([new_product.key])
10 changes: 3 additions & 7 deletions activity_browser/actions/activity/activity_redo_allocation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from qtpy import QtGui
from logging import getLogger

from multifunctional.database import SIMAPRO_ATTRIBUTES

from activity_browser import signals
from activity_browser.actions.base import ABAction, exception_dialogs
from activity_browser.mod import bw2data as bd
Expand All @@ -24,16 +22,14 @@ def run(node: bd.Node):
if not getattr(node, "multifunctional", None):
return
try:
is_simapro = any(
key in bd.databases[node['database']] for key in SIMAPRO_ATTRIBUTES
) or bd.databases[node['database']].get("products_as_process")

node.allocate(products_as_process=is_simapro)
node.allocate()

signals.new_statusbar_message.emit(f"Allocation values for process {node} updated.")
except KeyError as exc:
signals.new_statusbar_message.emit("A property for the allocation calculation was not found!")
log.error(f"A property for the allocation calculation was not found: {node}")
raise exc
except ZeroDivisionError as exc:
signals.new_statusbar_message.emit(str(exc))
log.error(f"Zero division in allocation calculation: {exc}")
raise exc
33 changes: 33 additions & 0 deletions activity_browser/actions/activity/function_substitute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from qtpy import QtWidgets, QtGui, QtCore

from activity_browser import application, bwutils
from activity_browser.actions.base import ABAction, exception_dialogs
from activity_browser.ui.icons import qicons

from bw_functional import Function


class FunctionSubstitute(ABAction):
"""
ABAction to open one or more supplied activities in an activity tab by employing signals.
TODO: move away from using signals like this. Probably add a method to the MainWindow to add a panel instead.
"""

icon = qicons.edit
text = "Substitute Function"

@staticmethod
@exception_dialogs
def run(function: tuple | int | Function, substitute: tuple | int | Function):
function = bwutils.refresh_node(function)
substitute = bwutils.refresh_node(substitute)

if not isinstance(function, Function):
return

if function.get("substitute") == substitute.key:
return

function.substitute(substitute.key)
function.save()
29 changes: 29 additions & 0 deletions activity_browser/actions/activity/function_substitute_remove.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from qtpy import QtWidgets, QtGui, QtCore

from activity_browser import application, bwutils
from activity_browser.actions.base import ABAction, exception_dialogs
from activity_browser.ui.icons import qicons

from bw_functional import Function


class FunctionSubstituteRemove(ABAction):
"""
ABAction to open one or more supplied activities in an activity tab by employing signals.
TODO: move away from using signals like this. Probably add a method to the MainWindow to add a panel instead.
"""

icon = qicons.edit
text = "Remove substitute"

@staticmethod
@exception_dialogs
def run(function: tuple | int | Function):
function = bwutils.refresh_node(function)

if not isinstance(function, Function):
return

function.substitute(None)
function.save()
18 changes: 8 additions & 10 deletions activity_browser/actions/activity/node_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from qtpy import QtWidgets, QtGui

from activity_browser import application
from activity_browser.actions.base import ABAction, exception_dialogs
from activity_browser.actions.activity.activity_redo_allocation import MultifunctionalProcessRedoAllocation
from activity_browser.mod import bw2data as bd
Expand All @@ -14,17 +15,14 @@ class NodeProperties(ABAction):
"""
# No icon for properties
icon = QtGui.QIcon()
text = "Node Properties"
text = "Function Properties"

@staticmethod
@exception_dialogs
def run(exchanges: List[Any], read_only: bool, parent: QtWidgets.QWidget):
if exchanges:
# Operates on the first, regardless of the selection length
target = exchanges[0]
activity = bd.get_activity(target.input.key)
def run(node_key: tuple, read_only: bool):
activity = bd.get_activity(node_key)

if PropertyEditor.edit_properties(activity, read_only, parent):
activity.save()
# Properties changed, redo allocations, the values might have changed
MultifunctionalProcessRedoAllocation.run(activity)
if PropertyEditor.edit_properties(activity, read_only, application.main_window):
activity.save()
# Properties changed, redo allocations, the values might have changed
MultifunctionalProcessRedoAllocation.run(activity)
Loading

0 comments on commit 1d34603

Please sign in to comment.