Skip to content
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

Autoformatting python source code #58

Open
kdheepak opened this issue Jun 16, 2024 · 1 comment
Open

Autoformatting python source code #58

kdheepak opened this issue Jun 16, 2024 · 1 comment

Comments

@kdheepak
Copy link
Contributor

kdheepak commented Jun 16, 2024

Hi! Firstly, thanks for developing and maintaining this project!

I wanted to check if you'd be interested in using an autoformatter for your source code?

At the moment, there's a number of lines that exceed conventional and unconventional character limits in Python projects (80 characters, 120 characters or even 150 characters per line) e.g.:

mTEPES.n2 = Set(initialize=mTEPES.nn, ordered=True , doc='load levels' , filter=lambda mTEPES,nn : nn in mTEPES.nn and sum(pDuration [p,sc,nn] for p,sc in mTEPES.ps) > 0)
mTEPES.g = Set(initialize=mTEPES.gg, ordered=False, doc='generating units' , filter=lambda mTEPES,gg : gg in mTEPES.gg and (pRatedMaxPowerElec [gg] > 0.0 or pRatedMaxCharge[gg] > 0.0 or pRatedMaxPowerHeat [gg] > 0.0) and pElecGenPeriodIni[gg] <= mTEPES.p.last() and pElecGenPeriodFin[gg] >= mTEPES.p.first() and pGenToNode.reset_index().set_index(['index']).isin(mTEPES.nd)['Node'][gg]) # excludes generators with empty node
mTEPES.t = Set(initialize=mTEPES.g , ordered=False, doc='thermal units' , filter=lambda mTEPES,g : g in mTEPES.g and pRatedLinearOperCost[g ] > 0.0)

This requires scrolling left to right on GitHub and in other text editors (where soft wrapping lines are not enabled) and makes it harder (in my humble opinion) to read some parts of the code.

There's also a number of lines where manual formatting of the spaces is used for aligning the code:

#%% generation parameters
pGenToNode = dfGeneration ['Node' ] # generator location in node
pGenToTechnology = dfGeneration ['Technology' ] # generator association to technology
pGenToExclusiveGen = dfGeneration ['MutuallyExclusive' ] # mutually exclusive generator
pIndBinUnitInvest = dfGeneration ['BinaryInvestment' ] # binary unit investment decision [Yes]
pIndBinUnitRetire = dfGeneration ['BinaryRetirement' ] # binary unit retirement decision [Yes]
pIndBinUnitCommit = dfGeneration ['BinaryCommitment' ] # binary unit commitment decision [Yes]
pIndBinStorInvest = dfGeneration ['StorageInvestment' ] # storage linked to generation investment [Yes]
pIndOperReserve = dfGeneration ['NoOperatingReserve' ] # no contribution to operating reserve [Yes]
pMustRun = dfGeneration ['MustRun' ] # must-run unit [Yes]
pInertia = dfGeneration ['Inertia' ] # inertia constant [s]
pElecGenPeriodIni = dfGeneration ['InitialPeriod' ] # initial period [year]
pElecGenPeriodFin = dfGeneration ['FinalPeriod' ] # final period [year]
pAvailability = dfGeneration ['Availability' ] # unit availability for adequacy [p.u.]
pEFOR = dfGeneration ['EFOR' ] # EFOR [p.u.]
pRatedMinPowerElec = dfGeneration ['MinimumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated minimum electric power [GW]
pRatedMaxPowerElec = dfGeneration ['MaximumPower' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated maximum electric power [GW]
pRatedMinPowerHeat = dfGeneration ['MinimumPowerHeat' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated minimum heat power [GW]
pRatedMaxPowerHeat = dfGeneration ['MaximumPowerHeat' ] * 1e-3 * (1.0-dfGeneration['EFOR']) # rated maximum heat power [GW]
pRatedLinearFuelCost = dfGeneration ['LinearTerm' ] * 1e-3 * dfGeneration['FuelCost'] # fuel term variable cost [MEUR/GWh]
pRatedConstantVarCost = dfGeneration ['ConstantTerm' ] * 1e-6 * dfGeneration['FuelCost'] # constant term variable cost [MEUR/h]
pLinearOMCost = dfGeneration ['OMVariableCost' ] * 1e-3 # O&M term variable cost [MEUR/GWh]
pOperReserveCost = dfGeneration ['OperReserveCost' ] * 1e-3 # operating reserve cost [MEUR/GW]

I really like how much consistency you've enforced in aligning the whitespace like this, it makes it easy to visually parse the structure of various sub-expressions in the code.

However, manually aligning the whitespace can be time-consuming. Changing a parameter name, or adding or removing an existing one will require a modeller to manually align these parameters again in order to continue maintaining consistency. This will increase the diff every time a modeller makes a contribution.

Furthermore, if a modeller were to make changes that they wish to contribute back to this project, the manual alignment of code like this can increase the chances of conflicts that would need to be resolved.

Would you consider using an autoformatter (black, ruff, yapf, autopep etc are commonly used ones) such that it autoformats the code when you save or when you commit code to a project? A number of these formatters have various options you can configure too, that you can tweak to your liking.

In my humble opinion, it would make it more easier to anyone to upstream changes or contributions.

But no worries if you choose not to adopt autoformatting! I know that the current style can make it very easy to read the code and there are certainly clear benefits to the current approach that you'd lose if you were to choose to adopt an autoformatter.

If you think this is not a direction you'd like to take the project, feel free to close the issue :)

@arght
Copy link
Contributor

arght commented Jun 17, 2024

Thanks for your comments. We will check the potential use of autoformatter for improving the code aspect while facilitating the contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants