Skip to content

Commit

Permalink
feat(cli): add command to filter a JSON array by key:value
Browse files Browse the repository at this point in the history
This is required to handle models with sensor groups
  • Loading branch information
mostaphaRoudsari committed Feb 17, 2021
1 parent 0f9a2c1 commit 522fbf0
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 3 deletions.
49 changes: 46 additions & 3 deletions honeybee_radiance_folder/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ def dynamic_scene(radiance_folder, model, outdoor, log_file):
sys.exit(0)


@folder.command('filter')
@folder.command('filter-folder')
@click.argument(
'folder', #type=click.Path(exists=True, file_okay=False, resolve_path=True)
'folder', type=click.Path(exists=True, file_okay=False, resolve_path=True)
)
@click.argument('pattern')
@click.option(
Expand Down Expand Up @@ -271,4 +271,47 @@ def filter_folder(folder, pattern, log_file):
else:
sys.exit(0)

# {stem, suffix, name, parent}

@folder.command('filter-file')
@click.argument(
'input-file',
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)
)
@click.argument('pattern', default='*:*')
@click.option('--output-file', '-of', type=click.File(mode='w'), default='-')
@click.option(
'--keep/--remove', is_flag=True, help='A flag to switch between keeping the objects '
'or removing them from the input list.', default=True, show_default=True
)
def filter_json_file(input_file, pattern, output_file, keep):
"""Filter a list fo JSON objects based on value for a specific key.
\b
Args:
input-file: Path to input JSON file. Input JSON file should be an array of
JSON objects.
pattern: Two string values separated by a ``:``. For example group:daylight
will keep/remove the objects when the value for group key is set to daylight.
"""
try:
key, value = [v.strip() for v in pattern.split(':')]

with open(input_file) as inf:
data = json.load(inf)

if key == value == '*':
# no filtering. pass the values as is.
output_file.write(json.dumps(data))
sys.exit(0)
if keep:
filtered_data = [obj for obj in data if obj[key] == value]
else:
filtered_data = [obj for obj in data if obj[key] != value]

output_file.write(json.dumps(filtered_data))
except Exception as e:
_logger.exception('Failed to filter objects in input file.\n{}'.format(e))
sys.exit(1)
else:
sys.exit(0)
56 changes: 56 additions & 0 deletions tests/assets/project_folder/grid_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[
{
"name": "west_window",
"identifier": "west_window",
"count": 96,
"group": "apertures"
},
{
"name": "east_window",
"identifier": "east_window",
"count": 96,
"group": "apertures"
},
{
"name": "north_window",
"identifier": "north_window",
"count": 64,
"group": "apertures"
},
{
"name": "south_window",
"identifier": "south_window",
"count": 64,
"group": "apertures"
},
{
"name": "Occ_Regions_East_T3_area",
"identifier": "Occ_Regions_East_T3_area",
"count": 1436,
"group": "occ_regions"
},
{
"name": "Occ_Regions_North_area",
"identifier": "Occ_Regions_North_area",
"count": 1106,
"group": "occ_regions"
},
{
"name": "Occ_Regions_West_T3_area",
"identifier": "Occ_Regions_West_T3_area",
"count": 1146,
"group": "occ_regions"
},
{
"name": "Occ_Regions_South_T4_area",
"identifier": "Occ_Regions_South_T4_area",
"count": 906,
"group": "occ_regions"
},
{
"name": "ground_floor",
"identifier": "ground_floor",
"count": 3196,
"group": "daylight_grids"
}
]
38 changes: 38 additions & 0 deletions tests/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from click.testing import CliRunner
from honeybee_radiance_folder.cli import filter_json_file
import json
import os


def test_filter_file():
runner = CliRunner()
input_file = './tests/assets/project_folder/grid_info.json'
output_file = './tests/assets/temp/grid_filtered_0.json'
result = runner.invoke(
filter_json_file, [
input_file, 'group:daylight_grids', '--output-file', output_file
]
)
assert result.exit_code == 0
# check the file is created
with open(output_file) as inf:
data = json.load(inf)
assert len(data) == 1
os.unlink(output_file)


def test_filter_file_remove():
runner = CliRunner()
input_file = './tests/assets/project_folder/grid_info.json'
output_file = './tests/assets/project_folder/grid_filtered_1.json'
result = runner.invoke(
filter_json_file, [
input_file, 'group:daylight_grids', '--output-file', output_file, '--remove'
]
)
assert result.exit_code == 0
# check the file is created
with open(output_file) as inf:
data = json.load(inf)
assert len(data) == 8
os.unlink(output_file)

0 comments on commit 522fbf0

Please sign in to comment.