Correct way to 'break' code into lines

Suppose if I have this long line of python line

mc.formLayout(self.topForm, edit=True, attachForm = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)],  attachControl = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)])

What is the best way to ā€˜break it upā€™ into multi lines? I am trying to do it in pep8 style to make it more organized

[QUOTE=salik89;30264]Suppose if I have this long line of python line

mc.formLayout(self.topForm, edit=True, attachForm = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)],  attachControl = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)])

What is the best way to ā€˜break it upā€™ into multi lines? I am trying to do it in pep8 style to make it more organized[/QUOTE]

Iā€™d declare the lists outside of the call to formLayout.


formAttach = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)]
controlAttach = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)]

mc.formLayout(self.topForm, edit=True, attachForm=formAttach, attachControl=controlAttachList)

Itā€™s much easier to read and if you needed to line-break you could cleanly do it after any of the comma separated values within the two lists.

[QUOTE=Jeff Hanna;30266]Iā€™d declare the lists outside of the call to formLayout.


formAttach = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)]
controlAttach = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)]

mc.formLayout(self.topForm, edit=True, attachForm=formAttach, attachControl=controlAttachList)

Itā€™s much easier to read and if you needed to line-break you could cleanly do it after any of the comma separated values within the two lists.[/QUOTE]

Hey, thanks for getting back to me.

As you are mentioning about the need to line-break, do you mean to say it will be as follows:

mc.formLayout(self.topForm, edit=True,
                            attachForm = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)],  
                            attachControl = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)])

PEP8 Style Guide For Python recommends a line length of 80 characters or less. This is a point of contention with some people maintaining that a max line length of 100 is fine. In any case we can meet this requirement easily here because anything within [], () or {} can be split into multiple lines and the interpreter will collapse the white space. Here is how I would do it.



mc.formLayout(
    self.topForm, 
    edit=True,
    attachForm=[
        (self.uiGrpField, 'left', 0), 
        (self.uiClrBtn, 'left', 0), 
        (self.uiLbl, 'left', 0),  
        (self.uiBtnOpt, 'left', 0), 
        (self.uiBtnHelp, 'left', 0), 
        (self.uiBtnReset, 'left', 0)
    ],  
    attachControl=[
        (self.uiSep, 'top', 5, self.uiBtnOpt), 
        (self.uiSep, 'top', 5, self.uiBtnHelp), 
        (self.uiSep, 'top', 5, self.uiBtnReset), 
        (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), 
        (self.uiBtnReset, 'left', 5, self.uiBtnOpt)
    ]
)


Some people try to condense their code into as few lines as possible, but, Iā€™d trade legibility for number of lines any day of the week. I think youā€™ll find a similar philosophy present in most of the python communities favorite libraries. Checkout requests, click, flask to see some realllllly clean code.

1 Like

[QUOTE=Jeff Hanna;30266]Iā€™d declare the lists outside of the call to formLayout.


formAttach = [(self.uiGrpField, 'left', 0), (self.uiClrBtn, 'left', 0), (self.uiLbl, 'left', 0),  (self.uiBtnOpt, 'left', 0), (self.uiBtnHelp, 'left', 0), (self.uiBtnReset, 'left', 0)]
controlAttach = [(self.uiSep, 'top', 5, self.uiBtnOpt), (self.uiSep, 'top', 5, self.uiBtnHelp), (self.uiSep, 'top', 5, self.uiBtnReset), (self.uiBtnOpt, 'left', 5, self.uiBtnHelp), (self.uiBtnReset, 'left', 5, self.uiBtnOpt)]

mc.formLayout(self.topForm, edit=True, attachForm=formAttach, attachControl=controlAttachList)

Itā€™s much easier to read and if you needed to line-break you could cleanly do it after any of the comma separated values within the two lists.[/QUOTE]

If you want to take it further in the PEP8 directionā€¦


formAttach = [
    (self.uiGrpField, 'left', 0),
    (self.uiClrBtn, 'left', 0),
    (self.uiLbl, 'left', 0),
    (self.uiBtnOpt, 'left', 0),
    (self.uiBtnHelp, 'left', 0),
    (self.uiBtnReset, 'left', 0)
]
controlAttach = [
    (self.uiSep, 'top', 5, self.uiBtnOpt),
    (self.uiSep, 'top', 5, self.uiBtnHelp),
    (self.uiSep, 'top', 5, self.uiBtnReset),
    (self.uiBtnOpt, 'left', 5, self.uiBtnHelp),
    (self.uiBtnReset, 'left', 5, self.uiBtnOpt)
]
mc.formLayout(self.topForm, edit=True, attachForm=formAttach,
    attachControl=controlAttachList)

I particularly like that style for lists in order to make it easier on the eyes when scanning.

More: PEP 8 ā€“ Style Guide for Python Code | peps.python.org

1 Like

Oh depending on how your logging, etc. is setup, avoiding doing too much on a single line or call can really make your traceback more specific. That can help cut down on debugging time.

1 Like

Thanks guys for the replies.
Still if you all doesnā€™t mind, can help taking a look to see if I am on the right track?
Truth be told, I am still somewhat confused about when to use camelCase, underscores etcā€¦

This LINK HEREis a portion that I have edited. Please do tell me if I am on the right track or notā€¦

Also, an off topic question though - how hard will it be if I will to convert/change all the maya ui layout commands into pyqt style?

The vertical list format in @DanBradhamā€™s example is nice. Iā€™d be careful about the way @MKapfhammer used the dedents, since that might cause issues in nested code, but itā€™s still quite readable.

You can also work around this specific problem with some specialized FormLayout helper functions to cut down on the boilerplate:

import maya.cmds as cmds
SIDES = ('top', 'left', 'bottom', 'right')
    
def dock_form(form, control, **sides):
    '''attach only to specified sides'''
    af = ((control, p, sides.get(p)) for p  in SIDES if sides.get(p, None) is not None)
    cmds.formLayout(form, e=True, attachForm = af)
    

w = cmds.window()
f = cmds.formLayout()
b = cmds.button()
dock(f, b, left=5, top=5, bottom=0, right = 24)
cmds.showWindow(w)

For a more elaborate method of making this maya GUI act like a modern layout language you can either jump straight to QT or try something like mGui which aims at a more object-oriented method:


from mGui.gui import *
from mGui.forms import *

form_spacing = {'margin': (4,4), 'spacing': (4,4)}

with Window(title='example') as example:
    with HeaderForm(css = form_spacing) as main:
        Text("I am some header text")
        with NavForm() as nav:
            with VerticalForm(css=form_spacing) as button_column:
                Button("example")
                Button("example 2")
                Button("example 3", height = 60)
                
            TextScrollList()
            
example.show()
                

which produces:


BTW if you use PyCharm, you can get most of the pep-8 compliance done neatly for you with a single hotkey!

1 Like

[QUOTE=Theodox;30289]Iā€™d be careful about the way @MKapfhammer used the dedents, since that might cause issues in nested code, but itā€™s still quite readable.[/QUOTE]

Thatā€™s straight out of PEP8. I can see it being an issue if you are referring to multiple calls occurring in a single nested line - depending on the traceback, you might not immediately know which thing is triggering the error. @Theodox, can you elaborate? I donā€™t think Iā€™m correctly picturing what youā€™re pointing out.

On a related note, you might also want to consider how it looks in whatever diffing tool your team is using in order to make pull requests/code reviews more obvious. The third item in the example below forces the reader to spend a bit more time figuring out what has changed.

 your_dict = {
     '1': 'a',
-    '2': 'b',
+    '2': 'c',
 }
 
 your_dict = {
     '1': 'a',
-    '2': 'b',
+    '2': 'c',
     }
 
-your_dict = {'1': 'a', '2': 'b'}
+your_dict = {'1': 'a', '2': 'c'}

I only meant the closing braces returning to the depth of the original line and not the depth of the list items. Actually on closer inspection danā€™s example does the same thing, itā€™s just disguised by the nesting of his code whereas it jumped out at me because you separated the lists from the application (which is otherwise a good thing).

Apart form ā€˜ā€™ā€™ strings, list closures like that are the only case where a lineā€™s ā€œchildrenā€ are at itā€™s own level, which makes vulnerable to depth changes. Itā€™s mostly a personal preference thing (are you a c# guy in another life? Itā€™s a common style there) but Iā€™m always prefer to either keep the closing bracket with the list or at the same dedent level as the list:


example = (
            1,
            2,
            3
           )

example = (
1,
2,
3
)

Iā€™ve actually never seen this style of line breaking used in Python code. A lot of this does have to do with preference, this obviously wonā€™t raise a SyntaxError, but, itā€™s neither PEP8 compliant nor a common practice. Then again if lines 2-5 are supposed to be a single indent weā€™re on the same page. The indentation of the closing parens is most commonly left at the same level as the reference youā€™re defining because it better indicates the indentation level of the current namespace. Here are some examples from the libraries I mentioned above:

https://github.com/kennethreitz/requests/blob/master/requests/models.py
https://github.com/pallets/flask/blob/master/flask/app.py

Iā€™d say flask is over-commented if it werenā€™t for the fact that itā€™s been downloaded over 12 million times. Libraries that get used that frequently need to be really well documented.

i was utterly unable to get the indents to line up in the editor. My main intention was not to put the ending bracket at the same level as the initial keyword, but with the contents so that it preserves the hanging-indent visual. In practice of course youā€™d never do it for data this sparse.

haha, I had a feeling thatā€™s what happened.

[QUOTE=Theodox;30297]i was utterly unable to get the indents to line up in the editor. My main intention was not to put the ending bracket at the same level as the initial keyword, but with the contents so that it preserves the hanging-indent visual. In practice of course youā€™d never do it for data this sparse.[/QUOTE]

Oh, ok. I understand you now. Thanks! :slight_smile:

PEP8 is a bit odd to me in some ways. This is one place where it says the closing parens can be at the level of the defining reference OR one tab in. Visually, the graphic designer in me cringes to see it at the same level - itā€™s easier for me to scan if that closing parens is indented (hanging indent). So I donā€™t disagree. Again, I was just using the most common example.

For me, it gets a lot worse to look at with the more nested lists I add. Iā€™ve started to feel that if Iā€™ve hit that point, it is a signal that a better design is needed on my part and I usually end up rewriting the mess into something less convoluted.

Exampleā€¦


a_list = [
    [
        nested_list1_item,
        [
            nested_list2_item,
            ],
        ]
    ]

While super nested data structures can often be a design/code smell. I much prefer keeping the open/close elements aligned with each other. I also tend to isolate them on their own line, makes it easier for me to comment out single elements.

Thanks, I will try and give it a whirlā€¦