Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python refactoring with rope and traad

abingham
September 20, 2014

Python refactoring with rope and traad

This is a short presentation on rope, a Python refactoring library, and traad, an HTTP server which exposes rope's functionality. Traad is aimed at simplifying rope integration with editors and IDEs, so this presentation looks at how that can be achieved.

abingham

September 20, 2014
Tweet

More Decks by abingham

Other Decks in Programming

Transcript

  1. ROPE HAS POWERFUL IDE- ORIENTED FEATURES Code completion Finding definitions

    and occurrences Organizing imports Looking up docstrings
  2. PROJECT Represents the files and directories containing code that rope

    will manipulate. P r o j e c t is the root object in rope
  3. CREATE A PROJECT f r o m r o p

    e . b a s e . p r o j e c t i m p o r t P r o j e c t p r o j e c t = P r o j e c t ( ' p r o j e c t _ d i r ' )
  4. WALK PROJECT RESOURCES d e f g e t _

    a l l _ r e s o u r c e s ( p r o j ) : t o d o = [ ' ' ] w h i l e t o d o : r e s _ p a t h = t o d o [ 0 ] t o d o = t o d o [ 1 : ] r e s = p r o j . g e t _ r e s o u r c e ( r e s _ p a t h ) y i e l d ( r e s . p a t h , r e s . i s _ f o l d e r ( ) ) i f r e s . i s _ f o l d e r ( ) : t o d o . e x t e n d ( ( c h i l d . p a t h f o r c h i l d i n r e s . g e t _ c h i l d r e n ( ) ) ) P r o j e c t . g e t _ r e s o u r c e ( p a t h ) finds a resource at a relative path R e s o u r c e . g e t _ c h i l d r e n ( ) returns an iterable over children
  5. MANAGE PREFERENCES p r e f s is a dict-like

    container of settings and preferences. f o r p i n p r o j e c t . p r e f s . p r e f s : p r i n t ( p r o j e c t . p r e f s . g e t ( p ) ) p r e f s are stored in a file called . r o p e p r o j e c t / c o n f i g . p y at the project's root directory.
  6. RESOURCES The files and directories in the project s e

    r v e r = p r o j e c t . g e t _ r e s o u r c e ( ' t r a a d / s e r v e r . p y ' ) p r i n t ( s e r v e r . n a m e , s e r v e r . p a t h , s e r v e r . i s _ f o l d e r ( ) ) c 1 = p r o j e c t . g e t _ r e s o u r c e ( ' ' ) . g e t _ c h i l d r e n ( ) [ 0 ] p r i n t ( c 1 . n a m e , c 1 . p a t h , c 1 . i s _ f o l d e r ( ) )
  7. CREATE THE REFACTORING OBJECT f r o m r o

    p e . r e f a c t o r . r e n a m e i m p o r t R e n a m e r e n = R e n a m e ( p r o j e c t , p r o j e c t . g e t _ r e s o u r c e ( ' t r a a d / s t a t e . p y ' ) , o f f s e t = 4 2 ) This can fail if rope can't perform the refactoring The refactoring is only partially bound
  8. CALCULATE ACTUAL CHANGES c h a n g e s

    = r e n . g e t _ c h a n g e s ( ' T a c o C o p t e r ' ) p r i n t ( c h a n g e s . d e s c r i p t i o n ) p r i n t ( c h a n g e s . g e t _ c h a n g e d _ r e s o u r c e s ( ) ) c h a n g e s represents a fully bound change
  9. EXECUTE THE CHANGES p r o j e c t

    . d o ( c h a n g e s ) After this the changes are actually performed.
  10. THE FULL PROCESS f r o m r o p

    e . b a s e . p r o j e c t i m p o r t P r o j e c t f r o m r o p e . r e f a c t o r . r e n a m e i m p o r t R e n a m e # C r e a t e t h e p r o j e c t p r o j = P r o j e c t ( ' . ' ) # C r e a t e t h e p a r t i a l l y - b o u n d r e f a c t o r i n g r e n = R e n a m e ( p r o j e c t , p r o j e c t . g e t _ r e s o u r c e ( ' t r a a d / s t a t e . p y ' ) , o f f s e t = 4 2 ) # C a l c u l a t e t h e c h a n g e s f o r a f u l l y - s p e c i f i e d r e n a m i n g c h a n g e = r e n . g e t _ c h a n g e s ( ' T a c o C o p t e r ' ) # P e r f o r m t h e c h a n g e s p r o j e c t . d o . c h a n g e s ( )
  11. H I S T O R Y OBJECT P r

    o j e c t . h i s t o r y manages the history of changes that have been made. Also remembers what has been undone as well as change dependencies.
  12. UNDOING CHANGES Undo the most recent changes p r o

    j e c t . h i s t o r y . u n d o ( ) Or select more distance changes to undo c h a n g e = p r o j e c t . h i s t o r y . u n d o _ l i s t [ 3 ] p r o j e c t . h i s t o r y . u n d o ( c h a n g e ) This will undo all dependent changes.
  13. REDOING CHANGES You can redo changes that you've previously undone.

    c h a n g e = p r o j e c t . h i s t o r y . r e d o _ l i s t [ - 2 ] p r o j e c t . h i s t o r y . r e d o ( c h a n g e )
  14. THE MULTI-PROJECT REFACTORING CLASS First create a M u l

    t i P r o j e c t R e f a c t o r i n g instance. f r o m r o p e . r e f a c t o r i m p o r t m u l t i p r o j e c t m p r = m u l t i p r o j e c t . M u l t i P r o j e c t R e f a c t o r i n g ( R e n a m e , # t y p e o f r e f a c t o r i n g t o p e r f o r m [ o t h e r _ p r o j e c t 1 , o t h e r _ p r o j e c t 2 , o t h e r _ p r o j e c t 3 ] ) Then call that with your main project and the refactoring initializer arguments r e f = m p r ( m a i n _ p r o j e c t , s o m e _ r e s o u r c e , o f f s e t = 1 3 3 7 )
  15. CREATE AND PERFORM THE CHANGE # R e m e

    m b e r t h a t ` r e f ` i s a r e n a m i n g o p e r a t i o n c h a n g e s = r e f . g e t _ a l l _ c h a n g e s ( " E n t e r p r i s e P r o x y M a n a g e r I m p l e m e n t a t i o n F a c t o r y F a c t o r y " ) m u l t i p r o j e c t . p e r f o r m ( c h a n g e s )
  16. WHAT IS TRAAD? tråd - svært tynn snor av fibrer

    av silke, ull, el. f eks av metall
  17. HTTP IS (WAY) MORE THAN FAST ENOUGH FOR THIS WORK

    The volume of data is low, and the response time only needs to be good enough for humans
  18. SUPPORT FOR MULTIPLE PYTHON VERSIONS The client has zero depenencies

    on the version of Python that traad is using
  19. PROPER LEVEL OF ABSTRACTION The problem domain of traad is

    Python refactoring, not Python integration with other languages.
  20. TASK STATE { 1 : { ' s t a

    t u s ' : ' p e n d i n g ' , ' d e s c r i p t i o n ' : ' R e n a m i n g F O O t o B A R ' , ' c h a n g e d _ r e s o u r c e s ' : [ . . . ] } , 2 : { ' s t a t u s ' : ' f a i l u r e ' } , 3 : { ' s t a t u s ' : ' s u c c e s s ' , ' c a l l t i p ' : ' u u i d 1 ( n o d e = N o n e , c l o c k _ s e q = N o n e ) ' } } Simple mapping of task-ids to dicts State is an actor and thus threadsafe. Multiple asynchronous tasks could be accessing it at any time.
  21. EMACS The emacs lisp for renaming looks like this ;

    S t a r t s n e w t r a a d s e r v e r o n t h e s p e c i f i e d d i r e c t o r y ( t r a a d - o p e n " ~ / p r o j e c t s / r o i d _ r a g e " ) ; R e n a m e s w h a t e v e r i s a t h e p o i n t ( i . e . u n d e r t h e c u r s o r ) ( t r a a d - r e n a m e " R a g i n g R o i d " ) And the HTTP message looks like this P O S T / r e f a c t o r / r e n a m e H T T P / 1 . 1 U s e r - A g e n t : c u r l / 7 . 3 0 . 0 H o s t : 1 2 7 . 0 . 0 . 1 : 6 5 1 7 2 A c c e p t : * / * A c c e p t - E n c o d i n g : d e f l a t e , g z i p C o n t e n t - T y p e : a p p l i c a t i o n / j s o n C o n t e n t - L e n g t h : 1 0 4 { " n a m e " : " R a g i n g R o i d " , " p a t h " : " \ / U s e r s \ / s i x t y n o r t h \ / p r o j e c t s \ / r o i d _ r a g e \ / r o i d _ r a g e \ / r o i d . p y " , " o f f s e t " : 1 0 2 }
  22. LINKS Rope - Traad - Pykka - Bottle - http://rope.sourceforge.net/

    http://github.com/abingham/traad http://www.pykka.org/ http://bottlepy.org/ http://github.com/abingham/traad_rope_presentation