-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fix silently ignoring file path in pvsystem.retrieve_sam
when name
is provided
#2020
Merged
kandersolar
merged 8 commits into
pvlib:main
from
echedey-ls:fix-retrieve-sam-unraised-exception
May 1, 2024
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
16c0ee1
My approach to the issue
echedey-ls 4ea8fb0
Deprecate previous parameters
echedey-ls a2b446f
No reason to over-engineer, right?
echedey-ls 405de69
Update v0.10.5.rst
echedey-ls 5b4aa4b
Update pvsystem.py
echedey-ls bce44f4
Improve error handling
echedey-ls 215c038
Add ppl involved
echedey-ls a8d1d15
kevin's suggestions
echedey-ls File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
import functools | ||
import io | ||
import itertools | ||
import os | ||
from pathlib import Path | ||
import inspect | ||
from urllib.request import urlopen | ||
import numpy as np | ||
|
@@ -1958,9 +1958,9 @@ def calcparams_pvsyst(effective_irradiance, temp_cell, | |
|
||
|
||
def retrieve_sam(name=None, path=None): | ||
''' | ||
Retrieve latest module and inverter info from a local file or the | ||
SAM website. | ||
""" | ||
Retrieve latest module and inverter info from a file bundled with pvlib, | ||
a path or an URL (like SAM's website). | ||
|
||
This function will retrieve either: | ||
|
||
|
@@ -1971,10 +1971,14 @@ def retrieve_sam(name=None, path=None): | |
|
||
and return it as a pandas DataFrame. | ||
|
||
.. note:: | ||
Only provide one of ``name`` or ``path``. | ||
|
||
Parameters | ||
---------- | ||
name : string, optional | ||
Name can be one of: | ||
Use one of the following strings to retrieve a database bundled with | ||
pvlib: | ||
|
||
* 'CECMod' - returns the CEC module database | ||
* 'CECInverter' - returns the CEC Inverter database | ||
|
@@ -1985,7 +1989,7 @@ def retrieve_sam(name=None, path=None): | |
* 'ADRInverter' - returns the ADR Inverter database | ||
|
||
path : string, optional | ||
Path to the SAM file. May also be a URL. | ||
Path to a CSV file or a URL. | ||
|
||
Returns | ||
------- | ||
|
@@ -1997,7 +2001,11 @@ def retrieve_sam(name=None, path=None): | |
Raises | ||
------ | ||
ValueError | ||
If no name or path is provided. | ||
If no ``name`` or ``path`` is provided. | ||
ValueError | ||
If both ``name`` and ``path`` are provided. | ||
KeyError | ||
If the provided ``name`` is not a valid database name. | ||
|
||
Notes | ||
----- | ||
|
@@ -2030,38 +2038,38 @@ def retrieve_sam(name=None, path=None): | |
CEC_Date NaN | ||
CEC_Type Utility Interactive | ||
Name: AE_Solar_Energy__AE6_0__277V_, dtype: object | ||
''' | ||
|
||
if name is not None: | ||
name = name.lower() | ||
data_path = os.path.join( | ||
os.path.dirname(os.path.abspath(__file__)), 'data') | ||
if name == 'cecmod': | ||
csvdata = os.path.join( | ||
data_path, 'sam-library-cec-modules-2019-03-05.csv') | ||
elif name == 'sandiamod': | ||
csvdata = os.path.join( | ||
data_path, 'sam-library-sandia-modules-2015-6-30.csv') | ||
elif name == 'adrinverter': | ||
csvdata = os.path.join( | ||
data_path, 'adr-library-cec-inverters-2019-03-05.csv') | ||
elif name in ['cecinverter', 'sandiainverter']: | ||
# Allowing either, to provide for old code, | ||
# while aligning with current expectations | ||
csvdata = os.path.join( | ||
data_path, 'sam-library-cec-inverters-2019-03-05.csv') | ||
else: | ||
raise ValueError(f'invalid name {name}') | ||
elif path is not None: | ||
if path.startswith('http'): | ||
response = urlopen(path) | ||
csvdata = io.StringIO(response.read().decode(errors='ignore')) | ||
else: | ||
csvdata = path | ||
""" | ||
# error: path was previously silently ignored if name was given GH#2018 | ||
if name is not None and path is not None: | ||
raise ValueError("Please provide either 'name' or 'path', not both.") | ||
elif name is None and path is None: | ||
raise ValueError("A name or path must be provided!") | ||
|
||
return _parse_raw_sam_df(csvdata) | ||
raise ValueError("Please provide either 'name' or 'path'.") | ||
elif name is not None: | ||
internal_dbs = { | ||
"cecmod": "sam-library-cec-modules-2019-03-05.csv", | ||
"sandiamod": "sam-library-sandia-modules-2015-6-30.csv", | ||
"adrinverter": "adr-library-cec-inverters-2019-03-05.csv", | ||
# Both 'cecinverter' and 'sandiainverter', point to same database | ||
# to provide for old code, while aligning with current expectations | ||
"cecinverter": "sam-library-cec-inverters-2019-03-05.csv", | ||
"sandiainverter": "sam-library-cec-inverters-2019-03-05.csv", | ||
} | ||
try: | ||
csvdata_path = Path(__file__).parent.joinpath( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general beware of placing too many executions in try-except or else isolating exceptions can be more difficult. Best to limit one operation with known exceptions |
||
"data", internal_dbs[name.lower()] | ||
) | ||
except KeyError: | ||
raise KeyError( | ||
f"Invalid name {name}. " | ||
+ f"Provide one of {list(internal_dbs.keys())}." | ||
) from None | ||
else: # path is not None | ||
if path.lower().startswith("http"): # URL check is not case-sensitive | ||
response = urlopen(path) # URL is case-sensitive | ||
csvdata_path = io.StringIO(response.read().decode(errors="ignore")) | ||
else: | ||
csvdata_path = path | ||
return _parse_raw_sam_df(csvdata_path) | ||
|
||
|
||
def _normalize_sam_product_names(names): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker, but anyone consider using a constant
INTERNAL_DBS
at the top of the module instead of defining it on every call?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like something only used in a function is better placed near it, and I doubt the extra computation time does save significant time when there will be two calls at most in a script.