diff --git a/.gitignore b/.gitignore index feb32f8..e0ce2d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ *.pyc *.cache + MANIFEST dist +*.egg-info build .idea + .pytest_cache gdxpds/test/pytest.log -*.egg-info diff --git a/dev/README.md b/dev/README.md index 608fca0..a0bf6fe 100644 --- a/dev/README.md +++ b/dev/README.md @@ -44,6 +44,7 @@ python ../../dev/md_to_rst.py md_files.txt - Delete the contents of `source/api`. - Run `sphinx-apidoc -o source/api ..` from the `doc` folder. - Compare `source/api/modules.rst` to `source/api.rst`. Delete `setup.rst` and references to it. +- Copy-paste the text in `gdxpds.postfix` at the bottom of `gdxpds.rst` - 'git push' changes to the documentation source code as needed. - Make the documentation per below diff --git a/doc/source/api.rst b/doc/source/api.rst index 550f5ce..f76be79 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -2,7 +2,6 @@ API ### .. toctree:: - :maxdepth: 4 + :maxdepth: 2 api/modules - api/gdxpds diff --git a/doc/source/api/gdxpds.rst b/doc/source/api/gdxpds.rst new file mode 100644 index 0000000..92707ee --- /dev/null +++ b/doc/source/api/gdxpds.rst @@ -0,0 +1,69 @@ +gdxpds package +============== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + gdxpds.test + +Submodules +---------- + +gdxpds.gdx module +----------------- + +.. automodule:: gdxpds.gdx + :members: + :undoc-members: + :show-inheritance: + +gdxpds.read\_gdx module +----------------------- + +.. automodule:: gdxpds.read_gdx + :members: + :undoc-members: + :show-inheritance: + +gdxpds.special module +--------------------- + +.. automodule:: gdxpds.special + :members: + :undoc-members: + :show-inheritance: + +gdxpds.tools module +------------------- + +.. automodule:: gdxpds.tools + :members: + :undoc-members: + :show-inheritance: + +gdxpds.write\_gdx module +------------------------ + +.. automodule:: gdxpds.write_gdx + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: gdxpds + :members: + :undoc-members: + :show-inheritance: + +.. autofunction:: gdxpds.to_dataframes + +.. autofunction:: gdxpds.to_dataframe + +.. autofunction:: gdxpds.list_symbols + +.. autofunction:: gdxpds.to_gdx diff --git a/doc/source/api/gdxpds.test.rst b/doc/source/api/gdxpds.test.rst new file mode 100644 index 0000000..08f3d35 --- /dev/null +++ b/doc/source/api/gdxpds.test.rst @@ -0,0 +1,61 @@ +gdxpds.test package +=================== + +Submodules +---------- + +gdxpds.test.conftest module +--------------------------- + +.. automodule:: gdxpds.test.conftest + :members: + :undoc-members: + :show-inheritance: + +gdxpds.test.test\_conversions module +------------------------------------ + +.. automodule:: gdxpds.test.test_conversions + :members: + :undoc-members: + :show-inheritance: + +gdxpds.test.test\_read module +----------------------------- + +.. automodule:: gdxpds.test.test_read + :members: + :undoc-members: + :show-inheritance: + +gdxpds.test.test\_session module +-------------------------------- + +.. automodule:: gdxpds.test.test_session + :members: + :undoc-members: + :show-inheritance: + +gdxpds.test.test\_specials module +--------------------------------- + +.. automodule:: gdxpds.test.test_specials + :members: + :undoc-members: + :show-inheritance: + +gdxpds.test.test\_write module +------------------------------ + +.. automodule:: gdxpds.test.test_write + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: gdxpds.test + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/modules.rst b/doc/source/api/modules.rst new file mode 100644 index 0000000..5262598 --- /dev/null +++ b/doc/source/api/modules.rst @@ -0,0 +1,7 @@ +gdx-pandas +========== + +.. toctree:: + :maxdepth: 4 + + gdxpds diff --git a/doc/source/conf.py b/doc/source/conf.py index 35f9365..70f961d 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -170,9 +170,10 @@ # -- Extension configuration ------------------------------------------------- -autoclass_content = 'both' -autodoc_member_order = 'bysource' -# Uncomment when https://github.com/sphinx-doc/sphinx/pull/4076 is -# released. -#autodoc_special_members = ['__getitem__', '__setitem__','__iter__'] +autodoc_default_options = { + 'autoclass_content': 'both', + 'member-order': 'bysource', + 'special-members': '__getitem__, __setitem__, __iter__', + 'undoc-members': True, +} numpy_show_class_member = True diff --git a/doc/source/gdxpds.postfix b/doc/source/gdxpds.postfix new file mode 100644 index 0000000..aafd390 --- /dev/null +++ b/doc/source/gdxpds.postfix @@ -0,0 +1,8 @@ + +.. autofunction:: gdxpds.to_dataframes + +.. autofunction:: gdxpds.to_dataframe + +.. autofunction:: gdxpds.list_symbols + +.. autofunction:: gdxpds.to_gdx diff --git a/doc/source/md_files.txt b/doc/source/md_files.txt index b20cee4..9015a7a 100644 --- a/doc/source/md_files.txt +++ b/doc/source/md_files.txt @@ -1,2 +1 @@ index -overview diff --git a/doc/source/overview.rst b/doc/source/overview.rst index 10730c4..3408f3b 100644 --- a/doc/source/overview.rst +++ b/doc/source/overview.rst @@ -1,12 +1,12 @@ -gdx-pandas overview -=================== +Overview +======== There are two main ways to use gdxpds. The first use case is the one that was initially supported: direct conversion between GDX files on disk and pandas DataFrames or a csv version thereof. Starting with the Version 1.0.0 rewrite, there is now a second style of use which involves -interfacing with GDX files and symbols via the ``gdxpds.gdx.GdxFile`` -and ``gdxpds.gdx.GdxSymbol`` classes. +interfacing with GDX files and symbols via the :py:class:`gdxpds.gdx.GdxFile` +and :py:class:`gdxpds.gdx.GdxSymbol` classes. `Direct Conversion <#direct-conversion>`__ \| `Backend Classes <#backend-classes>`__ @@ -20,14 +20,14 @@ pandas.DataFrame}, where each pandas.DataFrame contains data for a single set, parameter, equation, or variable. For sets and parameters, the last column of the DataFrame is assumed to contain the value of the element, which for sets should be ``True``, and for parameters should be -a ``float`` (or one of the ``gdxpds.gdx.NUMPY_SPECIAL_VALUES``). +a ``float`` (or one of the :py:const:`gdxpds.special.NUMPY_SPECIAL_VALUES`). Equations and variables have additional ‘value’ columns, in particular a level, a marginal value, a lower bound, an upper bound, and a scale, as -enumerated in ``gdxpds.gdx.GamsValueType``. These values are all assumed +enumerated in :py:class:`gdxpds.gdx.GamsValueType`. These values are all assumed to be found in the last five columns of the DataFrame, also see -``gdxpds.gdx.GAMS_VALUE_COLS_MAP``. +:py:data:`gdxpds.gdx.GAMS_VALUE_COLS_MAP`. -The basic interface to convert from GDX to DataFrames is: +The basic interface to convert from GDX to DataFrames is :py:func:`gdxpds.to_dataframes`: .. code:: python @@ -38,7 +38,7 @@ The basic interface to convert from GDX to DataFrames is: for symbol_name, df in dataframes.items(): print(f"Doing work with {symbol_name}\n{df}.") -And vice-versa: +And vice-versa we have :py:func:`gdxpds.to_gdx`: .. code:: python @@ -50,13 +50,13 @@ And vice-versa: gdx_file = 'C:\path_to_my_output_gdx\data_to_send_to_gams.gdx' gdx = gdxpds.to_gdx(data_ready_for_GAMS, gdx_file) -Note that providing a gdx_file is optional, and the returned gdx is an -object of type ``gdxpds.gdx.GdxFile``. +Note that providing a gdx_file path is optional. In either case the in-memory gdx file is +returned as an object of type :py:class:`gdxpds.gdx.GdxFile`. Additional functions include: -- ``gdxpds.list_symbols`` -- ``gdxpds.to_dataframe`` (If the call to this method includes +- :py:func:`gdxpds.list_symbols` +- :py:func:`gdxpds.to_dataframe` (If the call to this method includes old_interface=False, then the return value will be a plain DataFrame, not a {‘symbol_name’: df} dict.) diff --git a/gdxpds/gdx.py b/gdxpds/gdx.py index 5e79dd3..4104858 100644 --- a/gdxpds/gdx.py +++ b/gdxpds/gdx.py @@ -374,6 +374,7 @@ class GamsEquationType(Enum): External = 53 + gdxcc.GMS_EQUTYPE_X Conic = 53 + gdxcc.GMS_EQUTYPE_C + class GamsValueType(Enum): Level = gdxcc.GMS_VAL_LEVEL # .l Marginal = gdxcc.GMS_VAL_MARGINAL # .m @@ -393,6 +394,9 @@ def _missing_(cls, value): GAMS_VALUE_COLS_MAP = defaultdict(lambda : [('Value',GamsValueType.Level.value)]) +""" +List of value columns provided for each :py:attr:`GamsValueType` +""" GAMS_VALUE_COLS_MAP[GamsDataType.Variable] = [(value_type.name, value_type.value) for value_type in GamsValueType] GAMS_VALUE_COLS_MAP[GamsDataType.Equation] = GAMS_VALUE_COLS_MAP[GamsDataType.Variable] @@ -405,6 +409,7 @@ def _missing_(cls, value): GamsValueType.Scale: 1.0 } + GAMS_VARIABLE_DEFAULT_LOWER_UPPER_BOUNDS = { GamsVariableType.Unknown: (-np.inf,np.inf), GamsVariableType.Binary: (0.0,1.0), @@ -418,6 +423,7 @@ def _missing_(cls, value): GamsVariableType.Semiint: (1.0,np.inf) } + class GdxSymbol(object): def __init__(self,name,data_type,dims=0,file=None,index=None, description='',variable_type=None,equation_type=None): diff --git a/gdxpds/special.py b/gdxpds/special.py index 388a068..85d26a6 100644 --- a/gdxpds/special.py +++ b/gdxpds/special.py @@ -4,12 +4,14 @@ import gdxcc import numpy as np +logger = logging.getLogger(__name__) + -# List of numpy special values in gdxGetSpecialValues order # 1E300, 2E300, 3E300, 4E300, 5E300 NUMPY_SPECIAL_VALUES = [None, np.nan, np.inf, -np.inf, np.finfo(float).eps] - -logger = logging.getLogger(__name__) +"""List of numpy special values in gdxGetSpecialValues order, i.e., +[None, np.nan, np.inf, -np.inf, np.finfo(float).eps] +""" def convert_gdx_to_np_svs(df, num_dims): diff --git a/gdxpds/tools.py b/gdxpds/tools.py index efcd7b6..3f7dc59 100644 --- a/gdxpds/tools.py +++ b/gdxpds/tools.py @@ -137,21 +137,22 @@ def __find_gams(self): return ret class NeedsGamsDir(object): - """ - Mix-in class that asserts that a GAMS directory is needed and provides the - methods required to find and access it. + """Mix-in class that asserts that a GAMS directory is needed and provides the methods + required to find and access it.""" - Attributes - ---------- - gams_dir : str - The GAMS directory whose value has either been directly set or has been - found using the GamsDirFinder class. - """ def __init__(self,gams_dir=None): self.gams_dir = gams_dir @property def gams_dir(self): + """ + The GAMS directory whose value has either been directly set or has been found using + the GamsDirFinder class. + + Returns + ------- + str + """ return self.__gams_dir @gams_dir.setter