Ϫf@dZddlZddlZddlZddlZddlZddlZddlmZddl m Z ddl m Z m Z mZmZmZmZmZmZmZddlmZddlmZej2dk7rdZnd Zd ej6d d Zd ej6d d ZdZGddeZdZdZ dZ!GddZ"GddeZ#GddeZ$GddeZ%Gdde"Z&Gdde&eZ'Gd d!eZ(Gd"d#eZ)y)$z Tests for L{twisted.python.release} and L{twisted.python._release}. All of these tests are skipped on platforms other than Linux, as the release is only ever performed on Linux. N)Version)release) GitCommand IVCSCommandNotWorkingDirectoryProject filePathDeltafindTwistedProjectsgetRepositoryCommand replaceInFile runCommand)FilePath)TestCasewin32z*Release toolchain only supported on POSIX.zpre-commit-ci-update-configPATH)GITHUB_HEAD_REFrz1234-some-branch-nameNot relevant within Debian.ceZdZdZdZy)ExternalTempdirTestCasez A test case which has mkdir make directories outside of the usual spot, so that Git commands don't interfere with the Twisted checkout. ctjtj}|jtj ||S)z) Make our own directory. )dir)tempfilemkdtemp gettempdir addCleanupshutilrmtree)selfnewDirs B/usr/lib/python3/dist-packages/twisted/python/test/test_release.pymktempzExternalTempdirTestCase.mktemp;s4!!h&9&9&;<  v. N)__name__ __module__ __qualname____doc__r!r"r rr5s  r"rctddd|jdjdjddgtddd|jdjdjddgy ) z Set some config in the repo that Git requires to make commits. This isn't needed in real usage, just for tests. @param path: The path to the Git repository. @type path: L{FilePath} gitconfigz--filez.gitz user.namez "someone"z user.emailz"someone@someplace.com"N)r childpathr,s r _gitConfigr.Dsx    JJv  $ $X . 3 3         JJv  $ $X . 3 3  %   r"cJtdd|jgt|y)z Run a git init, and set some config that git requires. This isn't needed in real usage. @param path: The path to where the Git repo will be created. @type path: L{FilePath} r)initN)r r,r.r-s r _gitInitr1bsvtyy)*tr"c6djt|i|S)z A convenience for generating _version.py data. @param args: Arguments to pass to L{Version}. @param kwargs: Keyword arguments to pass to L{Version}. z0from incremental import Version __version__={!r})formatr)argskwargss r genVersionr6ns$ ? E E   r"ceZdZdZdZdZy)StructureAssertingMixinz A mixin for L{TestCase} subclasses which provides some methods for asserting the structure and contents of directories and files on the filesystem. c&|D]}|j|}t||tr&|j|j |||M|j ||j dtjjy)a# Create a set of directories and files given a dict defining their structure. @param root: The directory in which to create the structure. It must already exist. @type root: L{FilePath} @param dirDict: The dict defining the structure. Keys should be strings naming files, values should be strings describing file contents OR dicts describing subdirectories. All files are written in binary mode. Any string values are assumed to describe text files and will have their newlines replaced with the platform-native newline convention. For example:: {"foofile": "foocontents", "bardir": {"barfile": "bar contents"}} @type dirDict: C{dict}  N) r+ isinstancedictcreateDirectorycreateStructure setContentreplaceoslinesepencode)rrootdirDictxr+s r r>z'StructureAssertingMixin.createStructures|( PAJJqME'!*d+%%'$$UGAJ7  !3!3D"**!E!L!L!NO  Pr"c|jDcgc]}|j}}|jD]\}}|j|}t |r|j ||nt |tr@|j |j|jd|j||nN|jjjtjd}|j!|||j#||r"|j%d|jd|yycc}w)a Assert that a directory is equivalent to one described by a dict. @param root: The filesystem directory to compare. @type root: L{FilePath} @param dirDict: The dict that should describe the contents of the directory. It should be the same structure as the C{dirDict} parameter to L{createStructure}. @type dirDict: C{dict} z is not a dir!r:zThere were extra children in z: N)childrenbasenameitemsr+callable assertTruer;r<isdirr,assertStructure getContentdecoder@rArB assertEqualremovefail) rrDrEeachrH pathSegment expectationr+actuals r rNz'StructureAssertingMixin.assertStructures15 @DMMO@@(/  ) $KJJ{+E $ E 23K. %**^/LM$$UK8))+224<rNr'r"r r8r8zs P8Or"r8c6eZdZdZdZd dZdZdZdZdZ y) ProjectTestsz= There is a first-class representation of a project. c@|jt|t|t|tjd}t|tjd}t ||D]+\}}|j|j |j -y)zA Assert that two lists of L{Project}s are equal. directory)keyN)rQlensortedoperator attrgetterzipr[)robservedProjectsexpectedProjectsobservedexpecteds r assertProjectsEqualz ProjectTests.assertProjectsEquals -.4D0EF! ("5"5k"B " ("5"5k"B #&&68H"I E Hh   X//1C1C D Er"Nc|t|j}|djd}|}|D]S}|j|}|j s|j |jdj dU|jdj |jdj t|jt|S)a( Make a Twisted-style project in the given base directory. @param baseDirectory: The directory to create files in (as a L{FilePath). @param version: The version information for the project. @return: L{Project} pointing to the created project. r.z __init__.pyr" newsfragments _version.py) rr!splitr+existsr=r?r6rCr)rversion baseDirectorysegmentsr[segments r makeProjectzProjectTests.makeProjects  $T[[]3M1:##C(!  ;G!0I##%))+ OOM * 5 5c :  ; (88: &11*g2F2M2M2OPy!!r"cjt|j}|D]}|j|||S)z Create a series of projects underneath a temporary base directory. @return: A L{FilePath} for the base directory. )rr!rq)rversionsrnrms r makeProjectszProjectTests.makeProjectss9 !/  5G   Wm 4 5r"cvd}|j|}|j|jt|y)z5 Project objects know their version. )twistedrN)rqrQ getVersionr)rrmprojects r test_getVersionzProjectTests.test_getVersions7'""7+ ++-w/@Ar"c|ttd}|jt|d|jzy)zH The representation of a Project is Project(directory). barz Project(%r)N)rrrQreprr[)rfoos r test_reprzProjectTests.test_reprs/huo& cMS]]$CDr"c |jdd}t|}|j|t|j dt|j dj dgy)z findTwistedStyleProjects finds all projects underneath a particular directory. A 'project' is defined by the existence of a 'newsfragments' directory and is returned as a Project object. )rrwr)zfoo.barrrr}N)rtr rfrr+)rrnprojectss r test_findTwistedStyleProjectsz*ProjectTests.test_findTwistedStyleProjectssi ))*:.chAndBreaks! HH[ ! HH[ ! Fr"N)rAgetcwd assertRaisesZeroDivisionErrorr runChdirSaferQ)rcwdrs r test_chdirzUtilityTests.test_chdirsE iik  +W-A-A:N biik*r"cd}tdd5}|j|ddd|jdd}tddditd5}|j |j |ddd|jdd}tddditd5}|j |j |dddy#1swYxYw#1swYjxYw#1swYyxYw)z L{replaceInFile} replaces data in a file based on a dict. A key from the dict that is found in the file is replaced with the corresponding value. zfoo hey hey $VER bar zrelease.replacewNz$VERz2.0.0z3.0.0)openwriter@r rQread)rcontentoutfrefs r test_replaceInFilezUtilityTests.test_replaceInFile!s - #S ) T JJw  ??673'&'):; # $ 1   QVVXx 0 1##GW5''7);< # $ 1   QVVXx 0 1 1   1 1  1 1s#C!C(!C*CC'*C3N)r#r$r%r&rrr'r"r rr s+ 1r"rc(eZdZdZdZdZdZdZy)FilePathDeltaTestsz% Tests for L{filePathDelta}. cb|jttdtddgy)zU L{filePathDelta} can create a simple relative path to a child path. /foo/barz /foo/bar/bazbazNrQr rrs r test_filePathDeltaSubdirz+FilePathDeltaTests.test_filePathDeltaSubdir;s*  (:.0H IE7 r"cd|jttdtdddgy)ze L{filePathDelta} can traverse upwards to create relative paths to siblings. rz/foo/baz..rNrrs r test_filePathDeltaSiblingDirz/FilePathDeltaTests.test_filePathDeltaSiblingDirCs,  (:.0D Ee} r"cd|jttdtdgdy)zx L{filePathDelta} can create relative paths to totally unrelated paths for maximum portability. rz /baz/quux)rrrquuxNrrs r test_filePathNoCommonElementsz0FilePathDeltaTests.test_filePathNoCommonElementsLs)  (:.0E F ' r"cd|jttdtdgdy)z L{filePathDelta} doesn't take into account final elements when comparing 2 paths, but stops at the first difference. z/foo/bar/bar/spamz/foo/bar/baz/spam)rrrspamNrrs r $test_filePathDeltaSimilarEndElementsz7FilePathDeltaTests.test_filePathDeltaSimilarEndElementsVs+  (#67BU9V W ' r"N)r#r$r%r&rrrrr'r"r rr6s    r"rc>eZdZdZdZdZdZdZdZdZ dZ d Z y ) CommandsTestMixinzF Test mixin for the VCS commands used by the release scripts. rc@t|j|_yr)rr!tmpDirrs r setUpzCommandsTestMixin.setUphst{{}- r"c|j|j}|j|jj |y)z Calling the C{ensureIsWorkingDirectory} VCS command's method on a valid working directory doesn't produce any error. N)makeRepositoryr assertIsNone createCommandensureIsWorkingDirectoryrreposDirs r 1test_ensureIsWorkingDirectoryWithWorkingDirectoryzCCommandsTestMixin.test_ensureIsWorkingDirectoryWithWorkingDirectoryks7 &&t{{3 $,,EEhOPr"cn|jt|jj|jy)z Calling the C{ensureIsWorkingDirectory} VCS command's method on an invalid working directory raises a L{NotWorkingDirectory} exception. N)rrrrrrs r 4test_ensureIsWorkingDirectoryWithNonWorkingDirectoryzFCommandsTestMixin.test_ensureIsWorkingDirectoryWithNonWorkingDirectoryss+      7 7 KK r"c|j|j}|j|jj |y)z Calling the C{isStatusClean} VCS command's method on a repository with no pending modifications returns C{True}. N)rrrLr isStatusCleanrs r test_statusCleanz"CommandsTestMixin.test_statusClean~s5 &&t{{3 **88BCr"c|j|j}|jdjd|j |j j |y)z Calling the C{isStatusClean} VCS command's method on a repository with no pending modifications returns C{False}. some-file somethingN)rrr+r? assertFalserrrs r test_statusNotCleanz%CommandsTestMixin.test_statusNotCleansN &&t{{3{#..|< ++99(CDr"cv|j|j}|jd}|jd|j ||j |j |jj||jd|j|j dy)zr Calling the C{remove} VCS command's method remove the specified path from the directory. rrFzFile still existsN) rrr+r?commitRepositoryrLrlrrRrestatr)rrtestFiles r test_removezCommandsTestMixin.test_removes &&t{{3>>+.L) h' )* !!(+ *,?@r"c |ddditdddddditdddddd d }|j|j}|j|||j |t |j jd }|jj|||j||y ) z The C{exportTo} VCS command's method export the content of the repository as identical in a specified directory. zHi this is 1.0.0.READMEzHi this is 1.0.0rvrxrz twisted.web)rirj)rirjweb)z README.rstrvexportN) r6rrr>rrr!r+rexportTorN)r structurer exportDirs r test_exportzCommandsTestMixin.test_exports ."*,>!?))Q1=&.0B%C#-mQ1#E  &&t{{3 Xy1 h'T[[]+11(;  ##Hi8 Y 2r"N) r#r$r%r&skiprrrrrrrr'r"r rras5 )D.Q  DE A3r"rc$eZdZdZdZeZdZdZy)GitCommandTestz^ Specific L{CommandsTestMixin} related to Git repositories through L{GitCommand}. rct||S)z Create a Git repository in the specified path. @type root: L{FilePath} @params root: The directory to create the Git repository into. @return: The path to the repository just created. @rtype: L{FilePath} )r1)rrDs r rzGitCommandTest.makeRepositorys  r"ctdd|jdgtj|jdzztdd|jdddgy) z Add and commit all the files from the Git repository specified. @type repository: L{FilePath} @params repository: The Git repository to commit into. r)z-Caddz/*commitz-mhopN)r r,glob)r repositorys r rzGitCommandTest.commitRepositorysO  D*//5 1DIIjooPT>T4U U  E4(D%HIr"N) r#r$r%r&rrrrrr'r"r rrs )DM  Jr"rc"eZdZdZdZdZdZy)RepositoryCommandDetectionTestz Test the L{getRepositoryCommand} to access the right set of VCS commands depending on the repository manipulated. c@t|j|_yr)rr!reposrs r rz$RepositoryCommandDetectionTest.setUpsdkkm, r"ct|jt|j}|j|ty)zV L{getRepositoryCommand} from a Git repository returns L{GitCommand}. N)r1rr assertIsr)rcmds r test_gitz'RepositoryCommandDetectionTest.test_gits, "4::. c:&r"cN|jtt|jy)z L{getRepositoryCommand} from a directory which doesn't look like a Git repository produces a L{NotWorkingDirectory} exception. N)rrr rrs r test_unknownRepositoryz5RepositoryCommandDetectionTest.test_unknownRepositorys -/CTZZPr"N)r#r$r%r&rrrr'r"r rrs -'Qr"rceZdZdZdZy)VCSCommandInterfaceTestszF Test that the VCS command classes implement their interface. cT|jtjty)z: L{GitCommand} implements L{IVCSCommand}. N)rLr implementedByrrs r rz!VCSCommandInterfaceTests.test_gits  11*=>r"N)r#r$r%r&rr'r"r rrs ?r"r)*r&rr_rArsysr incrementalrtwisted.pythonrtwisted.python._releaserrrrr r r r r twisted.python.filepathrtwisted.trial.unittestrplatformrenvironPRECOMMIT_CI_ENVIRONGENERIC_CI_ENVIRONrr.r1r6r8rYrrrrrrr'r"r rs   "   -+<<7 D 7D5 JJv  / JJv  % h <  ;O;O|Q *Q h'1*'1T( ( VS3/S3l!J&(?!JHQ%<Q2 ?x ?r"