ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- PK`=]YY)__pycache__/revision.cpython-37.opt-1.pycnu[B M!V'u@sddlZddlZddlmZddlmZddlmZedZGddde Z Gdd d e Z Gd d d e Z Gd d d e Z GdddeZGdddeZddZdS)N)util)compatz(?:(.+?)@)?(\w+)?((?:\+|-)\d+)c@s eZdZdS) RevisionErrorN)__name__ __module__ __qualname__r r H/opt/alt/python37/lib/python3.7/site-packages/alembic/script/revision.pyr srcseZdZfddZZS)RangeNotAncestorErrorcs0||_||_tt|d|pd|p$dfdS)Nz-Revision %s is not an ancestor of revision %sbase)loweruppersuperr __init__)selfr r) __class__r r rs  zRangeNotAncestorError.__init__)rrrr __classcell__r r )rr r sr cseZdZfddZZS) MultipleHeadscs.||_||_tt|d|d|fdS)Nz6Multiple heads are present for given argument '%s'; %sz, )headsargumentrrrjoin)rrr)rr r rs  zMultipleHeads.__init__)rrrrrr r )rr rsrcseZdZfddZZS)ResolutionErrorcstt||||_dS)N)rrrr)rmessager)rr r r$szResolutionError.__init__)rrrrrr r )rr r#src@s eZdZdZddZejddZejddZejdd Z ejd d Z ejd d Z ddZ d7ddZ ddZd8ddZd9ddZddZddZdd Zd!d"Zd:d#d$Zd;d%d&Zdd/d0Zd?d1d2Zd@d3d4ZdAd5d6ZdS)B RevisionMapzMaintains a map of :class:`.Revision` objects. :class:`.RevisionMap` is used by :class:`.ScriptDirectory` to maintain and traverse the collection of :class:`.Script` objects, which are themselves instances of :class:`.Revision`. cCs ||_dS)a Construct a new :class:`.RevisionMap`. :param generator: a zero-arg callable that will generate an iterable of :class:`.Revision` instances to be used. These are typically :class:`.Script` subclasses within regular Alembic use. N) _generator)r generatorr r r r2szRevisionMap.__init__cCs |j|jS)zAll "head" revisions as strings. This is normally a tuple of length one, unless unmerged branches are present. :return: a tuple of string revision numbers. ) _revision_mapr)rr r r r<s zRevisionMap.headscCs |j|jS)zAll "base" revisions as strings. These are revisions that have a ``down_revision`` of None, or empty tuple. :return: a tuple of string revision numbers. )rbases)rr r r rIs zRevisionMap.basescCs |j|jS)zeAll "real" head revisions as strings. :return: a tuple of string revision numbers. )r _real_heads)rr r r rVszRevisionMap._real_headscCs |j|jS)zeAll "real" base revisions as strings. :return: a tuple of string revision numbers. )r _real_bases)rr r r r `szRevisionMap._real_basesc Csi}t}t}d|_d|_t}t}x|D]}|j|krTtd|j|||j<|j rn| ||j r~| || |j| |j|j r|j|jf7_|j r6|j|jf7_q6Wx|D]}|||qWx|D]}|||qWxr|D]f}x^|jD]T}||kr4td||f||} | |||jkr\||||qWqWd|d<|d<t||_t||_x|D]}|j||ddqW|S)z_memoized attribute, initializes the revision map from the initial collection. r z%Revision %s is present more than oncez-Revision %s referenced from %s is not presentNF)map_branch_labels)sqlautilZ OrderedSetrr setrrevisionrwarn branch_labelsadd dependenciesis_base _is_real_base_map_branch_labels_add_depends_onvalues_all_down_revisions add_nextrev_versioned_down_revisionsdiscardtuplerr _add_branches) rmap_rrZhas_branch_labelsZhas_depends_onr$revdownrev down_revisionr r r rjsT                  zRevisionMap._revision_mapcCsD|jr@x8|jD].}||kr4td||j||jf|||<qWdS)Nz;Branch name '%s' in revision %s already used by revision %s)r&_orig_branch_labelsrr$)rr$r4 branch_labelr r r r+s zRevisionMap._map_branch_labelsTcCs|r||||jr|j|jx(|j|g|ddD]}|j|jq8W|}x6|r|js|js|j|j|jr||j}qTPqTWdS)NF)include_dependencies)r+r&update_get_descendant_nodes_is_real_branch_pointis_merge_pointr7)rr$r4r!Znodeparentr r r r3s  zRevisionMap._add_branchescs*|jr&tfddt|jD|_dS)Nc3s|]}|jVqdS)N)r$).0Zdep)r4r r sz.RevisionMap._add_depends_on..)r(r2rto_tuple_resolved_dependencies)rr$r4r )r4r r,s zRevisionMap._add_depends_onFcs"|j}|s&j|kr&tdjn|rBj|krBtdj|j<||||jr||jjf7_j r|j jf7_ x6j D],}||krtd|f|| qWj rtfdd|jDjf|_jrtfdd|jDjf|_dS)zadd a single revision to an existing map. This method is for single-revision use cases, it's not appropriate for fully populating an entire revision map. z%Revision %s is present more than oncezrevision %s not in mapz-Revision %s referenced from %s is not presentc3s*|]"}|tjjgkr|VqdS)N)r#r.unionr$)r@head)r$r r rAsz+RevisionMap.add_revision..c3s*|]"}|tjjgkr|VqdS)N)r#r0rDr$)r@rE)r$r r rAsN)rr$rr% Exceptionr3r,r)rr*r r.r/ _is_real_headr2ris_headr)rr$_replacer4r6r )r$r add_revisions6       zRevisionMap.add_revisionNcCsL|j}|r|||}t|dkr8t||r2d|nd|rD|dSdSdS)aReturn the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :param branch_label: optional branch name which will limit the heads considered to those which include that branch_label. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` z%s@headrErN)rfilter_for_lineagelenr)rr9Z current_headsr r r get_current_heads  zRevisionMap.get_current_headcCs||j|S)N)rLr)rZ identifierr r r _get_base_revisionsszRevisionMap._get_base_revisionscsTt|ttttfr*tfdd|DdS|\}tfdd|DSdS)aReturn the :class:`.Revision` instances with the given rev id or identifiers. May be given a single identifier, a sequence of identifiers, or the special symbols "head" or "base". The result is a tuple of one or more identifiers, or an empty tuple in the case of "base". In the cases where 'head', 'heads' is requested and the revision map is empty, returns an empty tuple. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. csg|]}|qSr ) get_revisions)r@Zid_elem)rr r +sz-RevisionMap.get_revisions..r c3s|]}|VqdS)N)_revision_for_ident)r@rev_id)r9rr r rA/sz,RevisionMap.get_revisions..N) isinstancelistr2r# frozensetsum_resolve_revision_number)rid_ resolved_idr )r9rr rPs  zRevisionMap.get_revisionscCs>||\}}t|dkr&t||n |r2|d}|||S)a Return the :class:`.Revision` instance with the given rev id. If a symbolic name such as "head" or "base" is given, resolves the identifier into the current head or base revision. If the symbolic name refers to multiples, :class:`.MultipleHeads` is raised. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. rKr)rXrMrrR)rrYrZr9r r r get_revision2s   zRevisionMap.get_revisionc Csby|j|}WnJtk rXy||}Wn"tk rNtd||YnX|SYnX|SdS)NzNo such branch: '%s')rKeyErrorrRr)rr9 branch_revZ nonbranch_revr r r _resolve_branchHs zRevisionMap._resolve_branchc s|r||}nd}y|j}Wntk rfdd|jD}|rV|||}|sjtdnFt|dkrtdddd|d d Dfn|j|d }YnX|r|dk r||j|jstd |j|f|S) Ncsg|]}|r|r|qSr ) startswith)r@x)rZr r rQ`sz3RevisionMap._revision_for_ident..zNo such revision or branch '%s'rKz)Multiple revisions start with '%s': %s...z, css|]}d|VqdS)z'%s'Nr )r@rr r r rAmsz2RevisionMap._revision_for_ident..rz*Revision %s is not a member of branch '%s') r^rr\rLrrMr_shares_lineager$)rrZZ check_branchr]r$revsr )rZr rRVs6     zRevisionMap._revision_for_identcsD|\}}g|r ||r.|fdd|DS)Ncs g|]}j|dr|qS))r:)rc)r@Ztg)r:rsharesr r rQsz2RevisionMap.filter_for_lineage..)rXappendextend)rtargetsZ check_againstr:rYr9r )r:rrer rLzs  zRevisionMap.filter_for_lineagecsh|sdSt|ts|}fddtj|ddD}ttj|g|dj |g|d |S)NTcs$g|]}t|ts|n|qSr )rTRevisionrR)r@Ztest_against_rev)rr r rQsz/RevisionMap._shares_lineage..r )default)r:) rTrirRrrBboolr#r<rD_get_ancestor_nodes intersection)rtargetZtest_against_revsr:r )rr rcs      zRevisionMap._shares_lineagecCst|tjr&d|kr&|dd\}}nd}|j|dkrZ|rN||j||fS|j|fSnT|dkr||}|rz|f|fSd|fSn*|dks|dkrd|fSt j |dd|fSdS)N@rKrrEr r )rj) rTr string_typessplitrrLrrrNrrB)rrYr9Z current_headr r r rXs"    z$RevisionMap._resolve_revision_numbercCst|tjr t|}|s$dSndSt|d}|d} |d} |rR| sRdnd} |r| rhd| } n"| r| dr|| } qd| } nd} |} n$| rd| } n| rd| } nd} |} t|j | | ||d }| r\| r| d | | f}n | | }| drd}nV| dkrt |d}n>t t |ddd }x,|D]}|j ||j kr8Pq8Wd}nd}|r|||| d}|s|rt |t|| krtd |t|fnJ|d||| }|s|rt |t|| krtd |t|ft|S) NrbrrKrz%s@headrEz%s@baser ) inclusive implicit_basez%s@%sz1Relative revision %s didn't produce %d migrations)rTrrp_relative_destinationmatchintgroupr_rU_iterate_revisionsr[rMranger$absriter)rZ destinationsourceZ is_upwardsrsrrassert_relative_lengthrvZrelativeZsymbolr9ZreldeltaZfrom_Zto_rdZ symbol_revindexZrange_r r r _relative_iteratesr                zRevisionMap._relative_iteratecCsJ|||d|||}|r|S|||d|||}|r8|S|j||||dS)auIterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Revision` objects. TF)rrrs)rry)rrr rsrrr~Zrelative_upperZrelative_lowerr r r iterate_revisionsszRevisionMap.iterate_revisionscCs(|rdd}ndd}|j||||dS)NcSs|jS)N) _all_nextrev)r5r r r *z3RevisionMap._get_descendant_nodes..cSs|jS)N)nextrev)r5r r r r,r)r4check)_iterate_related_revisions)rrhr4rr:fnr r r r<&s  z!RevisionMap._get_descendant_nodescCs(|rdd}ndd}|j||||dS)NcSs|jS)N)r.)r5r r r r6rz1RevisionMap._get_ancestor_nodes..cSs|jS)N)r0)r5r r r r8r)r4r)r)rrhr4rr:rr r r rl2s  zRevisionMap._get_ancestor_nodesc #sdkr|jt}t}x|D]}|||r:t}xT|r|} |rV|| | |kr`q<|| |fdd|| D| Vq.z=Requested revision %s overlaps with other requested revisions) rr# collectionsdequerfpopr'rgrm differencerr$) rrrhr4rseentodornZ per_targetr5r )r4r r>s,     z&RevisionMap._iterate_related_revisionsc#sb|}t|tjo|d}t|}|s>|s>ttj |dd}|rf |} n|r|rt |} t |} t} | |  | } x6| D].}x(|j D]}j|| krPqW| |qW| |} n>|rtj} | |} n|stj} n|} tdd|Dddj | ddDs^t||tfddfddDDtfd d|D}d}xrR|std d }|s|tfd dDd dd|x`|rL|}|jd}|fddt|j D|sB||krBq|VqWqWr^tdS)ziterate revisions from upper to lower. The traversal is depth-first within branches, and breadth-first across branches as a whole. z@baseT)rcss|] }|jVqdS)N)r$)r@r5r r r rAsz1RevisionMap._iterate_revisions..css|] }|jVqdS)N)r$)r@r5r r r rAsc3s,|]$}|jrt|jdkr|VqdS)rKN)r=rMrmr)r@r5) total_spacer r rAsc3s|]}j|VqdS)N)r)r@r5)rr r rAsc3s|]}|jkr|VqdS)N)r$)r@ra)rr r rAsz5Dependency resolution failed; iteration can't proceedFc3s|]}|js|VqdS)N)rrm)r@r5)rr r rAscSs|jr dSdS)NrrK)is_branch_point)r5r r r rrz0RevisionMap._iterate_revisions..)keycs,g|]$}j|kr|krj|qSr )r)r@r6) branch_todorrr r rQsz2RevisionMap._iterate_revisions..N)rPrTrrpendswithrZ dedupe_tuple StopIterationr#rlrOr<rr.rr'rDr rmr rrr extendleftsorteddifference_updatepopleftremover$reversedAssertionError)rrr rrrsZrequested_lowersZlimit_to_lower_branchZuppersZupper_ancestorsZlowersZlower_ancestorsZlower_descendantsZ base_lowersZcandidate_lowersr5r6rZtotal_space_modifiedr )rrrr ryZs~            zRevisionMap._iterate_revisions)T)F)N)N)F)F)FFT)NFT)NFT)F)TF)rrr__doc__rrZmemoized_propertyrrrr rr+r3r,rJrNrOrPr[r^rRrLrcrXrrr<rlrryr r r r r)s6     ;  *  %  N  rc@seZdZdZeZeZdZdZdZ dZ dddZ ddZ ddZ ed d Zed d Zed dZeddZeddZeddZeddZeddZeddZdS)riaoBase class for revisioned objects. The :class:`.Revision` class is the base of the more public-facing :class:`.Script` object, which represents a migration script. The mechanics of revision management and traversal are encapsulated within :class:`.Revision`, while :class:`.Script` applies this logic to Python files in a version directory. NcCs@||_t||_t||_d|_tj|dd|_t|j|_ dS)Nr )rj) r$tuple_rev_as_scalarr7r(rCrrBr8r#r&)rr$r7r(r&r r r rs   zRevision.__init__cCsVt|jt|jg}|jr*|d|j|jr@|d|jd|jjd|fS)Nzdependencies=%rzbranch_labels=%rz%s(%s)z, ) reprr$r7r(rfr&rrr)rargsr r r __repr__ s zRevision.__repr__cCs4|j|jg|_|j|jkr0|j|jg|_dS)N)rrDr$r0r)rr$r r r r/s zRevision.add_nextrevcCstj|jdd|jS)Nr )rj)rrBr7rC)rr r r r.szRevision._all_down_revisionscCstj|jddS)Nr )rj)rrBr7)rr r r r0!sz"Revision._versioned_down_revisionscCs t|j S)aReturn True if this :class:`.Revision` is a 'head' revision. This is determined based on whether any other :class:`.Script` within the :class:`.ScriptDirectory` refers to this :class:`.Script`. Multiple heads can be present. )rkr)rr r r rH%s zRevision.is_headcCs t|j S)N)rkr)rr r r rG0szRevision._is_real_headcCs |jdkS)zXszRevision.is_merge_point)NN)rrrrrVrrr$r7r(r&rrr/propertyr.r0rHrGr)r*rr=r>r r r r ris&        ricCs$|sdSt|dkr|dS|SdS)NrKr)rM)r5r r r r_s  r)rerrZ sqlalchemyr"rcompilerurFrr rrobjectrrirr r r r s$      3 PK`=]ĂYY#__pycache__/revision.cpython-37.pycnu[B M!V'u@sddlZddlZddlmZddlmZddlmZedZGddde Z Gdd d e Z Gd d d e Z Gd d d e Z GdddeZGdddeZddZdS)N)util)compatz(?:(.+?)@)?(\w+)?((?:\+|-)\d+)c@s eZdZdS) RevisionErrorN)__name__ __module__ __qualname__r r H/opt/alt/python37/lib/python3.7/site-packages/alembic/script/revision.pyr srcseZdZfddZZS)RangeNotAncestorErrorcs0||_||_tt|d|pd|p$dfdS)Nz-Revision %s is not an ancestor of revision %sbase)loweruppersuperr __init__)selfr r) __class__r r rs  zRangeNotAncestorError.__init__)rrrr __classcell__r r )rr r sr cseZdZfddZZS) MultipleHeadscs.||_||_tt|d|d|fdS)Nz6Multiple heads are present for given argument '%s'; %sz, )headsargumentrrrjoin)rrr)rr r rs  zMultipleHeads.__init__)rrrrrr r )rr rsrcseZdZfddZZS)ResolutionErrorcstt||||_dS)N)rrrr)rmessager)rr r r$szResolutionError.__init__)rrrrrr r )rr r#src@s eZdZdZddZejddZejddZejdd Z ejd d Z ejd d Z ddZ d7ddZ ddZd8ddZd9ddZddZddZdd Zd!d"Zd:d#d$Zd;d%d&Zdd/d0Zd?d1d2Zd@d3d4ZdAd5d6ZdS)B RevisionMapzMaintains a map of :class:`.Revision` objects. :class:`.RevisionMap` is used by :class:`.ScriptDirectory` to maintain and traverse the collection of :class:`.Script` objects, which are themselves instances of :class:`.Revision`. cCs ||_dS)a Construct a new :class:`.RevisionMap`. :param generator: a zero-arg callable that will generate an iterable of :class:`.Revision` instances to be used. These are typically :class:`.Script` subclasses within regular Alembic use. N) _generator)r generatorr r r r2szRevisionMap.__init__cCs |j|jS)zAll "head" revisions as strings. This is normally a tuple of length one, unless unmerged branches are present. :return: a tuple of string revision numbers. ) _revision_mapr)rr r r r<s zRevisionMap.headscCs |j|jS)zAll "base" revisions as strings. These are revisions that have a ``down_revision`` of None, or empty tuple. :return: a tuple of string revision numbers. )rbases)rr r r rIs zRevisionMap.basescCs |j|jS)zeAll "real" head revisions as strings. :return: a tuple of string revision numbers. )r _real_heads)rr r r rVszRevisionMap._real_headscCs |j|jS)zeAll "real" base revisions as strings. :return: a tuple of string revision numbers. )r _real_bases)rr r r r `szRevisionMap._real_basesc Csi}t}t}d|_d|_t}t}x|D]}|j|krTtd|j|||j<|j rn| ||j r~| || |j| |j|j r|j|jf7_|j r6|j|jf7_q6Wx|D]}|||qWx|D]}|||qWxr|D]f}x^|jD]T}||kr4td||f||} | |||jkr\||||qWqWd|d<|d<t||_t||_x|D]}|j||ddqW|S)z_memoized attribute, initializes the revision map from the initial collection. r z%Revision %s is present more than oncez-Revision %s referenced from %s is not presentNF)map_branch_labels)sqlautil OrderedSetrr setrrevisionrwarn branch_labelsadd dependenciesis_base _is_real_base_map_branch_labels_add_depends_onvalues_all_down_revisions add_nextrev_versioned_down_revisionsdiscardtuplerr _add_branches) rmap_rrZhas_branch_labelsZhas_depends_onr%revdownrev down_revisionr r r rjsT                  zRevisionMap._revision_mapcCsD|jr@x8|jD].}||kr4td||j||jf|||<qWdS)Nz;Branch name '%s' in revision %s already used by revision %s)r'_orig_branch_labelsrr%)rr%r5 branch_labelr r r r,s zRevisionMap._map_branch_labelsTcCs|r||||jr|j|jx(|j|g|ddD]}|j|jq8W|}x6|r|js|js|j|j|jr||j}qTPqTWdS)NF)include_dependencies)r,r'update_get_descendant_nodes_is_real_branch_pointis_merge_pointr8)rr%r5r!nodeparentr r r r4s  zRevisionMap._add_branchescs*|jr&tfddt|jD|_dS)Nc3s|]}|jVqdS)N)r%).0dep)r5r r sz.RevisionMap._add_depends_on..)r)r3rto_tuple_resolved_dependencies)rr%r5r )r5r r-s zRevisionMap._add_depends_onFcs"|j}|s&j|kr&tdjn|rBj|krBtdj|j<||||jr||jjf7_j r|j jf7_ x6j D],}||krtd|f|| qWj rtfdd|jDjf|_jrtfdd|jDjf|_dS)zadd a single revision to an existing map. This method is for single-revision use cases, it's not appropriate for fully populating an entire revision map. z%Revision %s is present more than oncezrevision %s not in mapz-Revision %s referenced from %s is not presentc3s*|]"}|tjjgkr|VqdS)N)r$r/unionr%)rBhead)r%r r rDsz+RevisionMap.add_revision..c3s*|]"}|tjjgkr|VqdS)N)r$r1rGr%)rBrH)r%r r rDsN)rr%rr& Exceptionr4r-r*rr+r r/r0 _is_real_headr3ris_headr)rr%_replacer5r7r )r%r add_revisions6       zRevisionMap.add_revisionNcCsL|j}|r|||}t|dkr8t||r2d|nd|rD|dSdSdS)aReturn the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :param branch_label: optional branch name which will limit the heads considered to those which include that branch_label. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` z%s@headrHrN)rfilter_for_lineagelenr)rr:Z current_headsr r r get_current_heads  zRevisionMap.get_current_headcCs||j|S)N)rOr)r identifierr r r _get_base_revisionsszRevisionMap._get_base_revisionscsTt|ttttfr*tfdd|DdS|\}tfdd|DSdS)aReturn the :class:`.Revision` instances with the given rev id or identifiers. May be given a single identifier, a sequence of identifiers, or the special symbols "head" or "base". The result is a tuple of one or more identifiers, or an empty tuple in the case of "base". In the cases where 'head', 'heads' is requested and the revision map is empty, returns an empty tuple. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. csg|]}|qSr ) get_revisions)rBZid_elem)rr r +sz-RevisionMap.get_revisions..r c3s|]}|VqdS)N)_revision_for_ident)rBrev_id)r:rr r rD/sz,RevisionMap.get_revisions..N) isinstancelistr3r$ frozensetsum_resolve_revision_number)rid_ resolved_idr )r:rr rTs  zRevisionMap.get_revisionscCs>||\}}t|dkr&t||n |r2|d}|||S)a Return the :class:`.Revision` instance with the given rev id. If a symbolic name such as "head" or "base" is given, resolves the identifier into the current head or base revision. If the symbolic name refers to multiples, :class:`.MultipleHeads` is raised. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. rNr)r\rPrrV)rr]r^r:r r r get_revision2s   zRevisionMap.get_revisionc Csby|j|}WnJtk rXy||}Wn"tk rNtd||YnX|SYnX|SdS)NzNo such branch: '%s')rKeyErrorrVr)rr: branch_revZ nonbranch_revr r r _resolve_branchHs zRevisionMap._resolve_branchc s|r||}nd}y|j}Wntk rfdd|jD}|rV|||}|sjtdnFt|dkrtdddd|d d Dfn|j|d }YnX|r|dk r||j|jstd |j|f|S) Ncsg|]}|r|r|qSr ) startswith)rBx)r^r r rU`sz3RevisionMap._revision_for_ident..zNo such revision or branch '%s'rNz)Multiple revisions start with '%s': %s...z, css|]}d|VqdS)z'%s'Nr )rBrr r r rDmsz2RevisionMap._revision_for_ident..rz*Revision %s is not a member of branch '%s') rbrr`rOrrPr_shares_lineager%)rr^Z check_branchrar%revsr )r^r rVVs6     zRevisionMap._revision_for_identcsD|\}}g|r ||r.|fdd|DS)Ncs g|]}j|dr|qS))r;)rg)rBtg)r;rsharesr r rUsz2RevisionMap.filter_for_lineage..)r\appendextend)rtargetsZ check_againstr;r]r:r )r;rrjr rOzs  zRevisionMap.filter_for_lineagecsh|sdSt|ts|}fddtj|ddD}ttj|g|dj |g|d |S)NTcs$g|]}t|ts|n|qSr )rXRevisionrV)rBZtest_against_rev)rr r rUsz/RevisionMap._shares_lineage..r )default)r;) rXrnrVrrEboolr$r=rG_get_ancestor_nodes intersection)rtargetZtest_against_revsr;r )rr rgs      zRevisionMap._shares_lineagecCst|tjr&d|kr&|dd\}}nd}|j|dkrZ|rN||j||fS|j|fSnT|dkr||}|rz|f|fSd|fSn*|dks|dkrd|fSt j |dd|fSdS)N@rNrrHr r )ro) rXr string_typessplitrrOrrrQrrE)rr]r:Z current_headr r r r\s"    z$RevisionMap._resolve_revision_numbercCst|tjr t|}|s$dSndSt|d}|d} |d} |rR| sRdnd} |r| rhd| } n"| r| dr|| } qd| } nd} |} n$| rd| } n| rd| } nd} |} t|j | | ||d }| r\| r| d | | f}n | | }| drd}nV| dkrt |d}n>t t |ddd }x,|D]}|j ||j kr8Pq8Wd}nd}|r|||| d}|s|rt |t|| krtd |t|fnJ|d||| }|s|rt |t|| krtd |t|ft|S) NrfrrNrz%s@headrHz%s@baser ) inclusive implicit_basez%s@%sz1Relative revision %s didn't produce %d migrations)rXrru_relative_destinationmatchintgrouprcrY_iterate_revisionsr_rPranger%absriter)rZ destinationsourceZ is_upwardsrxrwassert_relative_lengthr{Zrelativesymbolr:Zreldeltafrom_to_rhZ symbol_revindexZrange_r r r _relative_iteratesr                zRevisionMap._relative_iteratecCsJ|||d|||}|r|S|||d|||}|r8|S|j||||dS)auIterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Revision` objects. TF)rwrx)rr~)rrr rxrwrZrelative_upperZrelative_lowerr r r iterate_revisionsszRevisionMap.iterate_revisionscCs(|rdd}ndd}|j||||dS)NcSs|jS)N) _all_nextrev)r6r r r *z3RevisionMap._get_descendant_nodes..cSs|jS)N)nextrev)r6r r r r,r)r5check)_iterate_related_revisions)rrmr5rr;fnr r r r=&s  z!RevisionMap._get_descendant_nodescCs(|rdd}ndd}|j||||dS)NcSs|jS)N)r/)r6r r r r6rz1RevisionMap._get_ancestor_nodes..cSs|jS)N)r1)r6r r r r8r)r5r)r)rrmr5rr;rr r r rq2s  zRevisionMap._get_ancestor_nodesc #sdkr|jt}t}x|D]}|||r:t}xT|r|} |rV|| | |kr`q<|| |fdd|| D| Vq.z=Requested revision %s overlaps with other requested revisions) rr$ collectionsdequerkpopr(rlrr differencerr%) rrrmr5rseentodorsZ per_targetr6r )r5r r>s,     z&RevisionMap._iterate_related_revisionsc#sb|}t|tjo|d}t|}|s>|s>ttj |dd}|rf |} n|r|rt |} t |} t} | |  | } x6| D].}x(|j D]}j|| krPqW| |qW| |} n>|rtj} | |} n|stj} n|} tdd|Dddj | ddDs^t||tfddfddDDtfd d|D}d}xrR|std d }|s|tfd dDd dd|x`|rL|}|jd}|fddt|j D|sB||krBq|VqWqWr^tdS)ziterate revisions from upper to lower. The traversal is depth-first within branches, and breadth-first across branches as a whole. z@baseT)rcss|] }|jVqdS)N)r%)rBr6r r r rDsz1RevisionMap._iterate_revisions..css|] }|jVqdS)N)r%)rBr6r r r rDsc3s,|]$}|jrt|jdkr|VqdS)rNN)r>rPrrr)rBr6) total_spacer r rDsc3s|]}j|VqdS)N)r)rBr6)rr r rDsc3s|]}|jkr|VqdS)N)r%)rBre)rr r rDsz5Dependency resolution failed; iteration can't proceedFc3s|]}|js|VqdS)N)rrr)rBr6)rr r rDscSs|jr dSdS)NrrN)is_branch_point)r6r r r rrz0RevisionMap._iterate_revisions..)keycs,g|]$}j|kr|krj|qSr )r)rBr7) branch_todorrr r rUsz2RevisionMap._iterate_revisions..N)rTrXrruendswithrZ dedupe_tuple StopIterationr$rqrSr=rr/rr(rGr rrr rrr extendleftsorteddifference_updatepopleftremover%reversedAssertionError)rrr rwrxZrequested_lowersZlimit_to_lower_branchZuppersZupper_ancestorsZlowersZlower_ancestorsZlower_descendantsZ base_lowersZcandidate_lowersr6r7rZtotal_space_modifiedr )rrrr r~Zs~            zRevisionMap._iterate_revisions)T)F)N)N)F)F)FFT)NFT)NFT)F)TF)rrr__doc__rrZmemoized_propertyrrrr rr,r4r-rMrQrSrTr_rbrVrOrgr\rrr=rqrr~r r r r r)s6     ;  *  %  N  rc@seZdZdZeZeZdZdZdZ dZ dddZ ddZ ddZ ed d Zed d Zed dZeddZeddZeddZeddZeddZeddZdS)rnaoBase class for revisioned objects. The :class:`.Revision` class is the base of the more public-facing :class:`.Script` object, which represents a migration script. The mechanics of revision management and traversal are encapsulated within :class:`.Revision`, while :class:`.Script` applies this logic to Python files in a version directory. NcCs@||_t||_t||_d|_tj|dd|_t|j|_ dS)Nr )ro) r%tuple_rev_as_scalarr8r)rFrrEr9r$r')rr%r8r)r'r r r rs   zRevision.__init__cCsVt|jt|jg}|jr*|d|j|jr@|d|jd|jjd|fS)Nzdependencies=%rzbranch_labels=%rz%s(%s)z, ) reprr%r8r)rkr'rrr)rargsr r r __repr__ s zRevision.__repr__cCs4|j|jg|_|j|jkr0|j|jg|_dS)N)rrGr%r1r)rr%r r r r0s zRevision.add_nextrevcCstj|jdd|jS)Nr )ro)rrEr8rF)rr r r r/szRevision._all_down_revisionscCstj|jddS)Nr )ro)rrEr8)rr r r r1!sz"Revision._versioned_down_revisionscCs t|j S)aReturn True if this :class:`.Revision` is a 'head' revision. This is determined based on whether any other :class:`.Script` within the :class:`.ScriptDirectory` refers to this :class:`.Script`. Multiple heads can be present. )rpr)rr r r rK%s zRevision.is_headcCs t|j S)N)rpr)rr r r rJ0szRevision._is_real_headcCs |jdkS)zPszRevision._is_real_branch_pointcCst|jdkS)z6Return True if this :class:`.Script` is a merge point.rN)rPr1)rr r r r?XszRevision.is_merge_point)NN)rrrrrZrrr%r8r)r'rrr0propertyr/r1rKrJr*r+rr>r?r r r r rns&        rncCs$|sdSt|dkr|dS|SdS)NrNr)rP)r6r r r r_s  r)rerrZ sqlalchemyr"rcompilerzrIrr rrobjectrrnrr r r r s$      3 PK`=]kRR__pycache__/base.cpython-37.pycnu[B M!Vi@sddlZddlZddlZddlZddlmZddlmZddlmZddlm Z ddl m Z e d Z e d Ze d Ze d Ze d ZdZe dZGdddeZGdddejZdS)N)util)compat)revision) migration)contextmanagerz(?!__init__)(.*\.py)(c|o)?$z(?!__init__)(.*\.py)$z([a-f0-9]+)\.py$z(upgrade|downgrade)_([a-z0-9]+)z\w+z%(rev)s_%(slug)sz,|(?: +)c@seZdZdZeddddfddZedd Zej d d Z d d Z e ddZ ed:ddZd;ddZddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zed.d/Zd0d1Zd2d3Zd4d5Z dGsz6ScriptDirectory._version_locations..r)r rrr joinr )rrrrrCs z"ScriptDirectory._version_locationsccsd|jrdd|jD}n|jg}x>|D]6}x0t|D]"}t|||}|dkrRq6|Vq6Wq&WdS)NcSsg|]}tj|r|qSr)rrexists)r"versrrrr$Psz3ScriptDirectory._load_revisions..)r rrrlistdirScript_from_filename)rpathsr'Zfile_scriptrrrrMs zScriptDirectory._load_revisionsc Cs|d}|dkrtd|d}|dk r6t|}|d}|rNt|}tt||dt||ddk|d d |d S) zProduce a new :class:`.ScriptDirectory` given a :class:`.Config` instance. The :class:`.Config` need only have the ``script_location`` key present. script_locationNz0No 'script_location' key found in configuration.rr r rtruerzutf-8)r rrrr ) Zget_main_optionrrint_split_on_space_commasplitr r!_default_file_template)clsconfigr-rr rrr from_config\s$       zScriptDirectory.from_configc csNy dVWn<tjk rr}zF|dkr.|j}|dkr<|j}|sDd}|||d}tt|Wdd}~XYntjk r}z8|sd}||p|j t |j d}tt|Wdd}~XYntj k r}z&|dkrd|j }tt|Wdd}~XYn<tj k rH} ztt| jdWdd} ~ XYnXdS)NzgRequested range %(start)s:%(end)s does not refer to ancestor/descendant revisions along the same branch)startendzMultiple head revisions are present for given argument '%(head_arg)s'; please specify a specific target revision, '@%(head_arg)s' to narrow to a specific head, or 'heads' for all heads)Zhead_argheadsz(Can't locate revision identified by '%s'r)rZRangeNotAncestorErrorlowerupperrZraise_from_causerrZ MultipleHeadsargumentformat_as_commar8ResolutionErrorZ RevisionErrorargs) rancestormultiple_headsr6r7 resolutionZrnaZmhreerrrrr_catch_revision_errors{s2    z&ScriptDirectory._catch_revision_errorsbaser8c csB|j||d*x"|jj||dddD] }|Vq&WWdQRXdS)aIterate through all revisions. :param base: the base revision, or "base" to start from the empty revision. :param head: the head revision; defaults to "heads" to indicate all head revisions. May also be "head" to indicate a single head revision. .. versionchanged:: 0.7.0 the "head" identifier now refers to the head of a non-branched repository only; use "heads" to refer to the set of all head branches simultaneously. )r6r7TF)Z inclusiveZassert_relative_lengthN)rDriterate_revisions)rrEheadrevrrrwalk_revisionsszScriptDirectory.walk_revisionsc Cs ||j|SQRXdS)zReturn the :class:`.Script` instance with the given rev identifier, symbolic name, or sequence of identifiers. .. versionadded:: 0.7.0 N)rDr get_revisions)rid_rrrrJs zScriptDirectory.get_revisionsc Cs ||j|SQRXdS)zReturn the :class:`.Script` instance with the given rev id. .. seealso:: :meth:`.ScriptDirectory.get_revisions` N)rDr get_revision)rrKrrrrLs zScriptDirectory.get_revisionc Cs8||j|\}}WdQRX|s,dS|dSdS)z[Convert a symbolic revision, i.e. 'head' or 'base', into an actual revision number.Nr)rDrZ_resolve_revision_number)rrKrHZ branch_namerrras_revision_numbers  z"ScriptDirectory.as_revision_numbercCs|j||S)aIterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Script` objects. .. seealso:: :meth:`.RevisionMap.iterate_revisions` )rrF)rr:r9rrrrFsz!ScriptDirectory.iterate_revisionsc Cs"|jdd |jSQRXdS)aGReturn the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` z}The script directory has multiple heads (due to branching).Please use get_heads(), or merge the branches using alembic merge.)r@N)rDrget_current_head)rrrrrNs z ScriptDirectory.get_current_headcCs t|jjS)aUReturn all "versioned head" revisions as strings. This is normally a list of length one, unless branches are present. The :meth:`.ScriptDirectory.get_current_head()` method can be used normally when a script directory has only one head. :return: a tuple of string revision numbers. )listrr8)rrrr get_headss zScriptDirectory.get_headscCs4|}t|dkr tdn|r,|dSdSdS)a#Return the "base" revision as a string. This is the revision number of the script that has a ``down_revision`` of None. If the script directory has multiple bases, an error is raised; :meth:`.ScriptDirectory.get_bases` should be preferred. rz@The script directory has multiple bases. Please use get_bases().rN) get_basesrrr)rbasesrrrget_bases  zScriptDirectory.get_basecCs t|jjS)zreturn all "base" revisions as strings. This is the revision number of all scripts that have a ``down_revision`` of None. .. versionadded:: 0.7.0 )rOrrR)rrrrrQ%s zScriptDirectory.get_basesc sNjd|d6jj||dd}t|}fddtt|DSQRXdS)NzFDestination %(end)s is not a valid upgrade target from current head(s))r?r7T)Z implicit_basecsg|]}tjj|qSr)r MigrationStepZupgrade_from_scriptr)r"r,)rrrr$8sz1ScriptDirectory._upgrade_revs..)rDrrFrOreversed)r destination current_revrevsr)rr _upgrade_revs0s   zScriptDirectory._upgrade_revsc s:jd|d"j||}fdd|DSQRXdS)NzHDestination %(end)s is not a valid downgrade target from current head(s))r?r7csg|]}tjj|qSr)rrTZdowngrade_from_scriptr)r"r,)rrrr$Dsz3ScriptDirectory._downgrade_revs..)rDrrF)rrVrWrXr)rr_downgrade_revs=s  zScriptDirectory._downgrade_revsc CsH|jdd0||}|jj||dd}g}||p>dg}x|D]}|dkrj|dd|DqFn ||krtqFt|j|g}t|j|g}||r||rt dd|D} t | |j dd} | | qFqF||rd d|D} t | |j dd} | | qFqFt d |j dd} | | qFqFW|SQRXdS) NzCMultiple heads are present; please specify a single target revision)r@T)Zinclude_dependenciescSsg|]}t|jdddqS)NFT)r StampStepr)r"rGrrrr$]sz/ScriptDirectory._stamp_revs..cSsg|] }|jqSr)r)r"rGrrrr$osFcSsg|] }|jqSr)r)r"rGrrrr$wsr)rDrJrZfilter_for_lineageextendsetZ_get_descendant_nodesZ_get_ancestor_nodes intersectionAssertionErrorrr[rappend) rrr8Zfiltered_headsZstepsZdestsdestZ descendantsZ ancestorsZ todo_headssteprrr _stamp_revsIsF          zScriptDirectory._stamp_revscCst|jddS)zRun the script environment. This basically runs the ``env.py`` script present in the migration environment. It is called exclusively by the command functions in :mod:`alembic.command`. zenv.pyN)rload_python_filer )rrrrrun_envs zScriptDirectory.run_envcCstjtj|jdS)Nzenv.py)rrr r%r )rrrrenv_py_locationszScriptDirectory.env_py_locationcKs*tjdtj|tj|||jf|dS)Nz Generating %s)rstatusrrr Ztemplate_to_filer)rsrcrakwrrr_generate_templates z"ScriptDirectory._generate_templatecCs"tdtj|tj||dS)Nz Generating %s)rrgrrr shutilcopy)rrhrarrr _copy_fileszScriptDirectory._copy_filecCs0tj|}tj|s,td|tj|dS)NzCreating directory %s)rrr r&rrgmakedirs)rrrrr_ensure_directorys   z!ScriptDirectory._ensure_directoryc  s$|dkr d}jddj|} WdQRXtt| t| krNtdtj} |dkrtj dkrx6| D]}|dk rtt j |j }PqtWtdnj }t j t j |} x.j D]} t j | | krPqWtd|jr||||| }|sBx0| D](}|dk r|jstd |jqW|r~(d d fd d t|DD}WdQRXjt j jd |ft|ttdd| Dt|t|| tj|dk r|ndd| t|}|r|j std|j||j fj!||S)a Generate a new revision file. This runs the ``script.py.mako`` template, given template arguments, and creates a new file. :param revid: String revision id. Typically this comes from ``alembic.util.rev_id()``. :param message: the revision message, the one passed by the -m argument to the ``revision`` command. :param head: the head revision to generate against. Defaults to the current "head" if no branches are present, else raises an exception. .. versionadded:: 0.7.0 :param splice: if True, allow the "head" version to not be an actual head; otherwise, the selected head must be a head (e.g. endpoint) revision. :param refresh: deprecated. NrGz{Multiple heads are present; please specify the head revision on which the new revision should be based, or perform a merge.)r@z"Duplicate head revisions specifiedrzAMultiple version locations present, please specify --version-pathz7Path %s is not represented in current version locationszeRevision %s is not a head revision; please specify --splice to create a new branch from this revisioncSs$g|]\}}||jkr|n|jqSr) branch_labelsr)r"rHdeprrrr$sz5ScriptDirectory.generate_revision..csg|]}j||fqSr)rrL)r"rq)rrrr$szscript.py.makocss |]}|dk r|jndVqdS)N)r)r"hrrr sz4ScriptDirectory.generate_revision..z empty message)Z up_revision down_revisionrp depends_on create_dateZcommamessagezVersion %s specified branch_labels %s, however the migration file %s does not have them; have you upgraded your script.py.mako to include the 'branch_labels' section?)"rDrrJrr]rrdatetimenowrrrdirnamernormpathr r ro _rev_pathis_headrZto_listrjr%r strZtuple_rev_as_scalartupleto_tupler<r) _from_pathrpZ add_revision)rZrevidrwrGZrefreshZsplicerpZ version_pathrurir8rvZ norm_pathZ vers_pathrr,r)rrgenerate_revisionsr           z!ScriptDirectory.generate_revisionc Cs~dt|pd}t||jkrD|d|jdddd}d|j|||j|j |j |j |j |j d}tj||S)N_rrz%s.py)rHslugyearmonthdayhourminutesecond)r%_slug_refindallr9rrrsplitr rrrrrrrr)rrrev_idrwrvrfilenamerrrr|szScriptDirectory._rev_path)NNNNN)rEr8)NFFNNN)#__name__ __module__ __qualname____doc__r2rpropertyrrZmemoized_propertyrr classmethodr5rrDrIrJrLrMrFrNrPrSrQrYrZrcrerfrjrmrorr|rrrrr sB    %        ;   or cseZdZdZfddZdZdZeddZeddZ ed d Z d d Z dddZ dddZ ddZeddZeddZZS)r)zRepresent a single revision file in a ``versions/`` directory. The :class:`.Script` instance is returned by methods such as :meth:`.ScriptDirectory.iterate_revisions`. c sN||_||_tt|j||jtjt|ddddtjt|ddddddS)Nrpr)defaultru)rp dependencies) modulersuperr)rrtrrgetattr)rrrr) __class__rrr6s zScript.__init__NcCstd|jdS)z)Return the docstring given in the script.z r)rBr1longdoc)rrrrdocHsz Script.doccCs6|jj}|r.t|jdr&||jj}|SdSdS)z)Return the docstring given in the script._alembic_source_encodingrN)rrhasattrdecoderstrip)rrrrrrNs  zScript.longdoccCsd|j|jrdnd|jrdnd|jr(dndf}|jrJ|d|f7}n|d|f7}|jrv|dt|j7}|jr|d t|j7}|j r|d t|j f7}|d |j f7}|d d dd|j D7}|S)NzRev: %s%s%s%s z (head)rz (branchpoint)z (mergepoint)z Merges: %s z Parent: %s zAlso depends on: %s zBranches into: %s zBranch names: %s z Path: %s z %s  css|]}d|VqdS)z %sNr)r"Zpararrrrswsz#Script.log_entry..)rr}is_branch_pointis_merge_point_format_down_revisionrrr<Znextrevrprr%r splitlines)rentryrrr log_entryZs.  zScript.log_entrycCs:d||j|jrdnd|jr"dnd|jr.dnd|jfS)Nz%s -> %s%s%s%s, %sz (head)rz (branchpoint)z (mergepoint))rrr}rrr)rrrr__str__}s   zScript.__str__FTcCs|j}|r<|jr,d|t|j|f}nd||f}|rZ|jrZ|dt|j7}|sb|r|d|jrpdnd|jr|jsdndf7}|r|d|jrdnd|j rd ndf7}|r|d |j 7}|S) Nz %s (%s) -> %sz%s -> %sz (%s)z%s%sz (head)rz (effective head)z (branchpoint)z (mergepoint)z, %s) rrrrr<rpZ _is_real_headr}rrr)rinclude_branches include_docinclude_parentstree_indicatorsZhead_indicatorstextrrr _head_onlys.     zScript._head_onlycCs|r |jS|||||SdS)N)rr)rverboserrrrrrr cmd_formats zScript.cmd_formatcCs|js dSt|jSdS)Nz)rtrr<Z_versioned_down_revisions)rrrrrszScript._format_down_revisioncCstj|\}}||||S)N)rrr1r*)r3 scriptdirrdir_rrrrrszScript._from_pathc Cs|jrt|}n t|}|s$dS|d}|jrR|ddk}|ddk}nd}}|sb|rtjtj||}tjtj||d} |s|r| rdSt ||} t | dst |} | st d|q| d} n| j} t| | tj||S)NrrcoFrzCould not determine revision id from filename %s. Be sure the 'revision' variable is declared inside the script (please see 'Upgrading from Alembic 0.1 to 0.2' in the documentation).)r_sourceless_rev_filematch_only_source_rev_filegrouprrr&r%rrdr _legacy_revrrr)) r3rrrZpy_matchZ py_filenameZis_cZis_oZ py_existsZ pyc_existsrmrrrrr*s2         zScript._from_filename)FFFTT)FFFT)rrrrrrrrrrrrrrrrrr* __classcell__rr)rrr)-s    #    r))rxrrBrkrrrrZruntimer contextlibrcompilerrrZ _mod_def_rerr2r0objectr ZRevisionr)rrrrs*           PK`=]-)__pycache__/__init__.cpython-37.opt-1.pycnu[B M!V[@sddlmZmZddgZdS))ScriptDirectoryScriptrrN)baserr__all__rrH/opt/alt/python37/lib/python3.7/site-packages/alembic/script/__init__.pysPK`=]i,RR%__pycache__/base.cpython-37.opt-1.pycnu[B M!Vi@sddlZddlZddlZddlZddlmZddlmZddlmZddlm Z ddl m Z e d Z e d Ze d Ze d Ze d ZdZe dZGdddeZGdddejZdS)N)util)compat)revision) migration)contextmanagerz(?!__init__)(.*\.py)(c|o)?$z(?!__init__)(.*\.py)$z([a-f0-9]+)\.py$z(upgrade|downgrade)_([a-z0-9]+)z\w+z%(rev)s_%(slug)sz,|(?: +)c@seZdZdZeddddfddZedd Zej d d Z d d Z e ddZ ed:ddZd;ddZddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zed.d/Zd0d1Zd2d3Zd4d5Z dGsz6ScriptDirectory._version_locations..r)r rrrjoinr )rrrrrCs z"ScriptDirectory._version_locationsccsd|jrdd|jD}n|jg}x>|D]6}x0t|D]"}t|||}|dkrRq6|Vq6Wq&WdS)NcSsg|]}tj|r|qSr)rrexists)r!versrrrr#Psz3ScriptDirectory._load_revisions..)r rrrlistdirScript_from_filename)rpathsr&Zfile_scriptrrrrMs zScriptDirectory._load_revisionsc Cs|d}|dkrtd|d}|dk r6t|}|d}|rNt|}tt||dt||ddk|d d |d S) zProduce a new :class:`.ScriptDirectory` given a :class:`.Config` instance. The :class:`.Config` need only have the ``script_location`` key present. script_locationNz0No 'script_location' key found in configuration.rr r rtruerzutf-8)r rrrr ) Zget_main_optionrrint_split_on_space_commasplitr r _default_file_template)clsZconfigr,rr rrr from_config\s$       zScriptDirectory.from_configc csNy dVWn<tjk rr}zF|dkr.|j}|dkr<|j}|sDd}|||d}tt|Wdd}~XYntjk r}z8|sd}||p|j t |j d}tt|Wdd}~XYntj k r}z&|dkrd|j }tt|Wdd}~XYn<tj k rH} ztt| jdWdd} ~ XYnXdS)NzgRequested range %(start)s:%(end)s does not refer to ancestor/descendant revisions along the same branch)startendzMultiple head revisions are present for given argument '%(head_arg)s'; please specify a specific target revision, '@%(head_arg)s' to narrow to a specific head, or 'heads' for all heads)Zhead_argheadsz(Can't locate revision identified by '%s'r)rZRangeNotAncestorErrorlowerupperrZraise_from_causerrZ MultipleHeadsZargumentformat_as_commar6ZResolutionErrorZ RevisionErrorargs) rancestormultiple_headsr4r5Z resolutionZrnaZmhreerrrrr_catch_revision_errors{s2    z&ScriptDirectory._catch_revision_errorsbaser6c csB|j||d*x"|jj||dddD] }|Vq&WWdQRXdS)aIterate through all revisions. :param base: the base revision, or "base" to start from the empty revision. :param head: the head revision; defaults to "heads" to indicate all head revisions. May also be "head" to indicate a single head revision. .. versionchanged:: 0.7.0 the "head" identifier now refers to the head of a non-branched repository only; use "heads" to refer to the set of all head branches simultaneously. )r4r5TF)Z inclusiveZassert_relative_lengthN)r?riterate_revisions)rr@headrevrrrwalk_revisionsszScriptDirectory.walk_revisionsc Cs ||j|SQRXdS)zReturn the :class:`.Script` instance with the given rev identifier, symbolic name, or sequence of identifiers. .. versionadded:: 0.7.0 N)r?r get_revisions)rid_rrrrEs zScriptDirectory.get_revisionsc Cs ||j|SQRXdS)zReturn the :class:`.Script` instance with the given rev id. .. seealso:: :meth:`.ScriptDirectory.get_revisions` N)r?r get_revision)rrFrrrrGs zScriptDirectory.get_revisionc Cs8||j|\}}WdQRX|s,dS|dSdS)z[Convert a symbolic revision, i.e. 'head' or 'base', into an actual revision number.Nr)r?rZ_resolve_revision_number)rrFrCZ branch_namerrras_revision_numbers  z"ScriptDirectory.as_revision_numbercCs|j||S)aIterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Script` objects. .. seealso:: :meth:`.RevisionMap.iterate_revisions` )rrA)rr8r7rrrrAsz!ScriptDirectory.iterate_revisionsc Cs"|jdd |jSQRXdS)aGReturn the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` z}The script directory has multiple heads (due to branching).Please use get_heads(), or merge the branches using alembic merge.)r<N)r?rget_current_head)rrrrrIs z ScriptDirectory.get_current_headcCs t|jjS)aUReturn all "versioned head" revisions as strings. This is normally a list of length one, unless branches are present. The :meth:`.ScriptDirectory.get_current_head()` method can be used normally when a script directory has only one head. :return: a tuple of string revision numbers. )listrr6)rrrr get_headss zScriptDirectory.get_headscCs4|}t|dkr tdn|r,|dSdSdS)a#Return the "base" revision as a string. This is the revision number of the script that has a ``down_revision`` of None. If the script directory has multiple bases, an error is raised; :meth:`.ScriptDirectory.get_bases` should be preferred. rz@The script directory has multiple bases. Please use get_bases().rN) get_basesrrr)rbasesrrrget_bases  zScriptDirectory.get_basecCs t|jjS)zreturn all "base" revisions as strings. This is the revision number of all scripts that have a ``down_revision`` of None. .. versionadded:: 0.7.0 )rJrrM)rrrrrL%s zScriptDirectory.get_basesc sNjd|d6jj||dd}t|}fddtt|DSQRXdS)NzFDestination %(end)s is not a valid upgrade target from current head(s))r;r5T)Z implicit_basecsg|]}tjj|qSr)r MigrationStepZupgrade_from_scriptr)r!r+)rrrr#8sz1ScriptDirectory._upgrade_revs..)r?rrArJreversed)r destination current_revrevsr)rr _upgrade_revs0s   zScriptDirectory._upgrade_revsc s:jd|d"j||}fdd|DSQRXdS)NzHDestination %(end)s is not a valid downgrade target from current head(s))r;r5csg|]}tjj|qSr)rrOZdowngrade_from_scriptr)r!r+)rrrr#Dsz3ScriptDirectory._downgrade_revs..)r?rrA)rrQrRrSr)rr_downgrade_revs=s  zScriptDirectory._downgrade_revsc CsH|jdd0||}|jj||dd}g}||p>dg}x|D]}|dkrj|dd|DqFn ||krtqFt|j|g}t|j|g}||r||rt dd|D} t | |j dd} | | qFqF||rd d|D} t | |j dd} | | qFqFt d |j dd} | | qFqFW|SQRXdS) NzCMultiple heads are present; please specify a single target revision)r<T)Zinclude_dependenciescSsg|]}t|jdddqS)NFT)r StampStepr)r!rBrrrr#]sz/ScriptDirectory._stamp_revs..cSsg|] }|jqSr)r)r!rBrrrr#osFcSsg|] }|jqSr)r)r!rBrrrr#wsr)r?rErZfilter_for_lineageextendsetZ_get_descendant_nodesZ_get_ancestor_nodes intersectionAssertionErrorrrVrappend) rrr6Zfiltered_headsZstepsZdestsdestZ descendantsZ ancestorsZ todo_headssteprrr _stamp_revsIsF          zScriptDirectory._stamp_revscCst|jddS)zRun the script environment. This basically runs the ``env.py`` script present in the migration environment. It is called exclusively by the command functions in :mod:`alembic.command`. zenv.pyN)rload_python_filer )rrrrrun_envs zScriptDirectory.run_envcCstjtj|jdS)Nzenv.py)rrrr$r )rrrrenv_py_locationszScriptDirectory.env_py_locationcKs*tjdtj|tj|||jf|dS)Nz Generating %s)rstatusrrrZtemplate_to_filer)rsrcr\kwrrr_generate_templates z"ScriptDirectory._generate_templatecCs"tdtj|tj||dS)Nz Generating %s)rrbrrrshutilcopy)rrcr\rrr _copy_fileszScriptDirectory._copy_filecCs0tj|}tj|s,td|tj|dS)NzCreating directory %s)rrrr%rrbmakedirs)rrrrr_ensure_directorys   z!ScriptDirectory._ensure_directoryc  s$|dkr d}jddj|} WdQRXtt| t| krNtdtj} |dkrtj dkrx6| D]}|dk rtt j |j }PqtWtdnj }t j t j |} x.j D]} t j | | krPqWtd|jr||||| }|sBx0| D](}|dk r|jstd |jqW|r~(d d fd d t|DD}WdQRXjt j jd |ft|ttdd| Dt|t|| tj|dk r|ndd| t|}|r|j std|j||j fj!||S)a Generate a new revision file. This runs the ``script.py.mako`` template, given template arguments, and creates a new file. :param revid: String revision id. Typically this comes from ``alembic.util.rev_id()``. :param message: the revision message, the one passed by the -m argument to the ``revision`` command. :param head: the head revision to generate against. Defaults to the current "head" if no branches are present, else raises an exception. .. versionadded:: 0.7.0 :param splice: if True, allow the "head" version to not be an actual head; otherwise, the selected head must be a head (e.g. endpoint) revision. :param refresh: deprecated. NrBz{Multiple heads are present; please specify the head revision on which the new revision should be based, or perform a merge.)r<z"Duplicate head revisions specifiedrzAMultiple version locations present, please specify --version-pathz7Path %s is not represented in current version locationszeRevision %s is not a head revision; please specify --splice to create a new branch from this revisioncSs$g|]\}}||jkr|n|jqSr) branch_labelsr)r!rCdeprrrr#sz5ScriptDirectory.generate_revision..csg|]}j||fqSr)rrG)r!rl)rrrr#szscript.py.makocss |]}|dk r|jndVqdS)N)r)r!hrrr sz4ScriptDirectory.generate_revision..z empty message)Z up_revision down_revisionrk depends_on create_dateZcommamessagezVersion %s specified branch_labels %s, however the migration file %s does not have them; have you upgraded your script.py.mako to include the 'branch_labels' section?)"r?rrErrXrrdatetimeZnowrrrdirnamernormpathrr rj _rev_pathis_headrZto_listrer$r strZtuple_rev_as_scalartupleto_tupler9r( _from_pathrkZ add_revision)rZrevidrrrBZrefreshZsplicerkZ version_pathrprdr6rqZ norm_pathZ vers_pathrr+r)rrgenerate_revisionsr           z!ScriptDirectory.generate_revisionc Cs~dt|pd}t||jkrD|d|jdddd}d|j|||j|j |j |j |j |j d}tj||S)N_rrz%s.py)rCslugyearmonthdayhourminutesecond)r$_slug_refindallr7rrrsplitr rrrrrrrr)rrrev_idrrrqrfilenamerrrrvszScriptDirectory._rev_path)NNNNN)r@r6)NFFNNN)#__name__ __module__ __qualname____doc__r1rpropertyrrZmemoized_propertyrr classmethodr3rr?rDrErGrHrArIrKrNrLrTrUr^r`rarerhrjr|rvrrrrr sB    %        ;   or cseZdZdZfddZdZdZeddZeddZ ed d Z d d Z dddZ dddZ ddZeddZeddZZS)r(zRepresent a single revision file in a ``versions/`` directory. The :class:`.Script` instance is returned by methods such as :meth:`.ScriptDirectory.iterate_revisions`. c sN||_||_tt|j||jtjt|ddddtjt|ddddddS)Nrkr)defaultrp)rk dependencies) modulersuperr(rrorrzgetattr)rrrr) __class__rrr6s zScript.__init__NcCstd|jdS)z)Return the docstring given in the script.z r)r=r0longdoc)rrrrdocHsz Script.doccCs6|jj}|r.t|jdr&||jj}|SdSdS)z)Return the docstring given in the script._alembic_source_encodingr~N)rrhasattrdecoderstrip)rrrrrrNs  zScript.longdoccCsd|j|jrdnd|jrdnd|jr(dndf}|jrJ|d|f7}n|d|f7}|jrv|dt|j7}|jr|d t|j7}|j r|d t|j f7}|d |j f7}|d d dd|j D7}|S)NzRev: %s%s%s%s z (head)r~z (branchpoint)z (mergepoint)z Merges: %s z Parent: %s zAlso depends on: %s zBranches into: %s zBranch names: %s z Path: %s z %s  css|]}d|VqdS)z %sNr)r!Zpararrrrnwsz#Script.log_entry..)rrwis_branch_pointis_merge_point_format_down_revisionrrr9Znextrevrkrr$r splitlines)rentryrrr log_entryZs.  zScript.log_entrycCs:d||j|jrdnd|jr"dnd|jr.dnd|jfS)Nz%s -> %s%s%s%s, %sz (head)r~z (branchpoint)z (mergepoint))rrrwrrr)rrrr__str__}s   zScript.__str__FTcCs|j}|r<|jr,d|t|j|f}nd||f}|rZ|jrZ|dt|j7}|sb|r|d|jrpdnd|jr|jsdndf7}|r|d|jrdnd|j rd ndf7}|r|d |j 7}|S) Nz %s (%s) -> %sz%s -> %sz (%s)z%s%sz (head)r~z (effective head)z (branchpoint)z (mergepoint)z, %s) rrrrr9rkZ _is_real_headrwrrr)rinclude_branches include_docinclude_parentstree_indicatorsZhead_indicatorstextrrr _head_onlys.     zScript._head_onlycCs|r |jS|||||SdS)N)rr)rverboserrrrrrr cmd_formats zScript.cmd_formatcCs|js dSt|jSdS)Nz)rorr9Z_versioned_down_revisions)rrrrrszScript._format_down_revisioncCstj|\}}||||S)N)rrr0r))r2 scriptdirrdir_rrrrr{szScript._from_pathc Cs|jrt|}n t|}|s$dS|d}|jrR|ddk}|ddk}nd}}|sb|rtjtj||}tjtj||d} |s|r| rdSt ||} t | dst |} | st d|q| d} n| j} t| | tj||S)NrrcoFrzCould not determine revision id from filename %s. Be sure the 'revision' variable is declared inside the script (please see 'Upgrading from Alembic 0.1 to 0.2' in the documentation).)r_sourceless_rev_filematch_only_source_rev_filegrouprrr%r$rr_r _legacy_revrrr() r2rrrZpy_matchZ py_filenameZis_cZis_oZ py_existsZ pyc_existsrmrrrrr)s2         zScript._from_filename)FFFTT)FFFT)rrrrrrrrrrrrrrrrr{r) __classcell__rr)rrr(-s    #    r()rsrr=rfr~rrrZruntimer contextlibrcompilerrrZ _mod_def_rerr1r/objectr ZRevisionr(rrrrs*           PK`=]-#__pycache__/__init__.cpython-37.pycnu[B M!V[@sddlmZmZddgZdS))ScriptDirectoryScriptrrN)baserr__all__rrH/opt/alt/python37/lib/python3.7/site-packages/alembic/script/__init__.pysPK`=]fYV'u'u revision.pynu[import re import collections from .. import util from sqlalchemy import util as sqlautil from ..util import compat _relative_destination = re.compile(r'(?:(.+?)@)?(\w+)?((?:\+|-)\d+)') class RevisionError(Exception): pass class RangeNotAncestorError(RevisionError): def __init__(self, lower, upper): self.lower = lower self.upper = upper super(RangeNotAncestorError, self).__init__( "Revision %s is not an ancestor of revision %s" % (lower or "base", upper or "base") ) class MultipleHeads(RevisionError): def __init__(self, heads, argument): self.heads = heads self.argument = argument super(MultipleHeads, self).__init__( "Multiple heads are present for given argument '%s'; " "%s" % (argument, ", ".join(heads)) ) class ResolutionError(RevisionError): def __init__(self, message, argument): super(ResolutionError, self).__init__(message) self.argument = argument class RevisionMap(object): """Maintains a map of :class:`.Revision` objects. :class:`.RevisionMap` is used by :class:`.ScriptDirectory` to maintain and traverse the collection of :class:`.Script` objects, which are themselves instances of :class:`.Revision`. """ def __init__(self, generator): """Construct a new :class:`.RevisionMap`. :param generator: a zero-arg callable that will generate an iterable of :class:`.Revision` instances to be used. These are typically :class:`.Script` subclasses within regular Alembic use. """ self._generator = generator @util.memoized_property def heads(self): """All "head" revisions as strings. This is normally a tuple of length one, unless unmerged branches are present. :return: a tuple of string revision numbers. """ self._revision_map return self.heads @util.memoized_property def bases(self): """All "base" revisions as strings. These are revisions that have a ``down_revision`` of None, or empty tuple. :return: a tuple of string revision numbers. """ self._revision_map return self.bases @util.memoized_property def _real_heads(self): """All "real" head revisions as strings. :return: a tuple of string revision numbers. """ self._revision_map return self._real_heads @util.memoized_property def _real_bases(self): """All "real" base revisions as strings. :return: a tuple of string revision numbers. """ self._revision_map return self._real_bases @util.memoized_property def _revision_map(self): """memoized attribute, initializes the revision map from the initial collection. """ map_ = {} heads = sqlautil.OrderedSet() _real_heads = sqlautil.OrderedSet() self.bases = () self._real_bases = () has_branch_labels = set() has_depends_on = set() for revision in self._generator(): if revision.revision in map_: util.warn("Revision %s is present more than once" % revision.revision) map_[revision.revision] = revision if revision.branch_labels: has_branch_labels.add(revision) if revision.dependencies: has_depends_on.add(revision) heads.add(revision.revision) _real_heads.add(revision.revision) if revision.is_base: self.bases += (revision.revision, ) if revision._is_real_base: self._real_bases += (revision.revision, ) # add the branch_labels to the map_. We'll need these # to resolve the dependencies. for revision in has_branch_labels: self._map_branch_labels(revision, map_) for revision in has_depends_on: self._add_depends_on(revision, map_) for rev in map_.values(): for downrev in rev._all_down_revisions: if downrev not in map_: util.warn("Revision %s referenced from %s is not present" % (downrev, rev)) down_revision = map_[downrev] down_revision.add_nextrev(rev) if downrev in rev._versioned_down_revisions: heads.discard(downrev) _real_heads.discard(downrev) map_[None] = map_[()] = None self.heads = tuple(heads) self._real_heads = tuple(_real_heads) for revision in has_branch_labels: self._add_branches(revision, map_, map_branch_labels=False) return map_ def _map_branch_labels(self, revision, map_): if revision.branch_labels: for branch_label in revision._orig_branch_labels: if branch_label in map_: raise RevisionError( "Branch name '%s' in revision %s already " "used by revision %s" % (branch_label, revision.revision, map_[branch_label].revision) ) map_[branch_label] = revision def _add_branches(self, revision, map_, map_branch_labels=True): if map_branch_labels: self._map_branch_labels(revision, map_) if revision.branch_labels: revision.branch_labels.update(revision.branch_labels) for node in self._get_descendant_nodes( [revision], map_, include_dependencies=False): node.branch_labels.update(revision.branch_labels) parent = node while parent and \ not parent._is_real_branch_point and \ not parent.is_merge_point: parent.branch_labels.update(revision.branch_labels) if parent.down_revision: parent = map_[parent.down_revision] else: break def _add_depends_on(self, revision, map_): if revision.dependencies: revision._resolved_dependencies = tuple( map_[dep].revision for dep in util.to_tuple(revision.dependencies) ) def add_revision(self, revision, _replace=False): """add a single revision to an existing map. This method is for single-revision use cases, it's not appropriate for fully populating an entire revision map. """ map_ = self._revision_map if not _replace and revision.revision in map_: util.warn("Revision %s is present more than once" % revision.revision) elif _replace and revision.revision not in map_: raise Exception("revision %s not in map" % revision.revision) map_[revision.revision] = revision self._add_branches(revision, map_) self._add_depends_on(revision, map_) if revision.is_base: self.bases += (revision.revision, ) if revision._is_real_base: self._real_bases += (revision.revision, ) for downrev in revision._all_down_revisions: if downrev not in map_: util.warn( "Revision %s referenced from %s is not present" % (downrev, revision) ) map_[downrev].add_nextrev(revision) if revision._is_real_head: self._real_heads = tuple( head for head in self._real_heads if head not in set(revision._all_down_revisions).union([revision.revision]) ) + (revision.revision,) if revision.is_head: self.heads = tuple( head for head in self.heads if head not in set(revision._versioned_down_revisions).union([revision.revision]) ) + (revision.revision,) def get_current_head(self, branch_label=None): """Return the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :param branch_label: optional branch name which will limit the heads considered to those which include that branch_label. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` """ current_heads = self.heads if branch_label: current_heads = self.filter_for_lineage(current_heads, branch_label) if len(current_heads) > 1: raise MultipleHeads( current_heads, "%s@head" % branch_label if branch_label else "head") if current_heads: return current_heads[0] else: return None def _get_base_revisions(self, identifier): return self.filter_for_lineage(self.bases, identifier) def get_revisions(self, id_): """Return the :class:`.Revision` instances with the given rev id or identifiers. May be given a single identifier, a sequence of identifiers, or the special symbols "head" or "base". The result is a tuple of one or more identifiers, or an empty tuple in the case of "base". In the cases where 'head', 'heads' is requested and the revision map is empty, returns an empty tuple. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. """ if isinstance(id_, (list, tuple, set, frozenset)): return sum([self.get_revisions(id_elem) for id_elem in id_], ()) else: resolved_id, branch_label = self._resolve_revision_number(id_) return tuple( self._revision_for_ident(rev_id, branch_label) for rev_id in resolved_id) def get_revision(self, id_): """Return the :class:`.Revision` instance with the given rev id. If a symbolic name such as "head" or "base" is given, resolves the identifier into the current head or base revision. If the symbolic name refers to multiples, :class:`.MultipleHeads` is raised. Supports partial identifiers, where the given identifier is matched against all identifiers that start with the given characters; if there is exactly one match, that determines the full revision. """ resolved_id, branch_label = self._resolve_revision_number(id_) if len(resolved_id) > 1: raise MultipleHeads(resolved_id, id_) elif resolved_id: resolved_id = resolved_id[0] return self._revision_for_ident(resolved_id, branch_label) def _resolve_branch(self, branch_label): try: branch_rev = self._revision_map[branch_label] except KeyError: try: nonbranch_rev = self._revision_for_ident(branch_label) except ResolutionError: raise ResolutionError( "No such branch: '%s'" % branch_label, branch_label) else: return nonbranch_rev else: return branch_rev def _revision_for_ident(self, resolved_id, check_branch=None): if check_branch: branch_rev = self._resolve_branch(check_branch) else: branch_rev = None try: revision = self._revision_map[resolved_id] except KeyError: # do a partial lookup revs = [x for x in self._revision_map if x and x.startswith(resolved_id)] if branch_rev: revs = self.filter_for_lineage(revs, check_branch) if not revs: raise ResolutionError( "No such revision or branch '%s'" % resolved_id, resolved_id) elif len(revs) > 1: raise ResolutionError( "Multiple revisions start " "with '%s': %s..." % ( resolved_id, ", ".join("'%s'" % r for r in revs[0:3]) ), resolved_id) else: revision = self._revision_map[revs[0]] if check_branch and revision is not None: if not self._shares_lineage( revision.revision, branch_rev.revision): raise ResolutionError( "Revision %s is not a member of branch '%s'" % (revision.revision, check_branch), resolved_id) return revision def filter_for_lineage( self, targets, check_against, include_dependencies=False): id_, branch_label = self._resolve_revision_number(check_against) shares = [] if branch_label: shares.append(branch_label) if id_: shares.extend(id_) return [ tg for tg in targets if self._shares_lineage( tg, shares, include_dependencies=include_dependencies)] def _shares_lineage( self, target, test_against_revs, include_dependencies=False): if not test_against_revs: return True if not isinstance(target, Revision): target = self._revision_for_ident(target) test_against_revs = [ self._revision_for_ident(test_against_rev) if not isinstance(test_against_rev, Revision) else test_against_rev for test_against_rev in util.to_tuple(test_against_revs, default=()) ] return bool( set(self._get_descendant_nodes([target], include_dependencies=include_dependencies)) .union(self._get_ancestor_nodes([target], include_dependencies=include_dependencies)) .intersection(test_against_revs) ) def _resolve_revision_number(self, id_): if isinstance(id_, compat.string_types) and "@" in id_: branch_label, id_ = id_.split('@', 1) else: branch_label = None # ensure map is loaded self._revision_map if id_ == 'heads': if branch_label: return self.filter_for_lineage( self.heads, branch_label), branch_label else: return self._real_heads, branch_label elif id_ == 'head': current_head = self.get_current_head(branch_label) if current_head: return (current_head, ), branch_label else: return (), branch_label elif id_ == 'base' or id_ is None: return (), branch_label else: return util.to_tuple(id_, default=None), branch_label def _relative_iterate( self, destination, source, is_upwards, implicit_base, inclusive, assert_relative_length): if isinstance(destination, compat.string_types): match = _relative_destination.match(destination) if not match: return None else: return None relative = int(match.group(3)) symbol = match.group(2) branch_label = match.group(1) reldelta = 1 if inclusive and not symbol else 0 if is_upwards: if branch_label: from_ = "%s@head" % branch_label elif symbol: if symbol.startswith("head"): from_ = symbol else: from_ = "%s@head" % symbol else: from_ = "head" to_ = source else: if branch_label: to_ = "%s@base" % branch_label elif symbol: to_ = "%s@base" % symbol else: to_ = "base" from_ = source revs = list( self._iterate_revisions( from_, to_, inclusive=inclusive, implicit_base=implicit_base)) if symbol: if branch_label: symbol_rev = self.get_revision( "%s@%s" % (branch_label, symbol)) else: symbol_rev = self.get_revision(symbol) if symbol.startswith("head"): index = 0 elif symbol == "base": index = len(revs) - 1 else: range_ = compat.range(len(revs) - 1, 0, -1) for index in range_: if symbol_rev.revision == revs[index].revision: break else: index = 0 else: index = 0 if is_upwards: revs = revs[index - relative - reldelta:] if not index and assert_relative_length and \ len(revs) < abs(relative - reldelta): raise RevisionError( "Relative revision %s didn't " "produce %d migrations" % (destination, abs(relative))) else: revs = revs[0:index - relative + reldelta] if not index and assert_relative_length and \ len(revs) != abs(relative) + reldelta: raise RevisionError( "Relative revision %s didn't " "produce %d migrations" % (destination, abs(relative))) return iter(revs) def iterate_revisions( self, upper, lower, implicit_base=False, inclusive=False, assert_relative_length=True): """Iterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Revision` objects. """ relative_upper = self._relative_iterate( upper, lower, True, implicit_base, inclusive, assert_relative_length ) if relative_upper: return relative_upper relative_lower = self._relative_iterate( lower, upper, False, implicit_base, inclusive, assert_relative_length ) if relative_lower: return relative_lower return self._iterate_revisions( upper, lower, inclusive=inclusive, implicit_base=implicit_base) def _get_descendant_nodes( self, targets, map_=None, check=False, include_dependencies=True): if include_dependencies: fn = lambda rev: rev._all_nextrev else: fn = lambda rev: rev.nextrev return self._iterate_related_revisions( fn, targets, map_=map_, check=check ) def _get_ancestor_nodes( self, targets, map_=None, check=False, include_dependencies=True): if include_dependencies: fn = lambda rev: rev._all_down_revisions else: fn = lambda rev: rev._versioned_down_revisions return self._iterate_related_revisions( fn, targets, map_=map_, check=check ) def _iterate_related_revisions(self, fn, targets, map_, check=False): if map_ is None: map_ = self._revision_map seen = set() todo = collections.deque() for target in targets: todo.append(target) if check: per_target = set() while todo: rev = todo.pop() if check: per_target.add(rev) if rev in seen: continue seen.add(rev) todo.extend( map_[rev_id] for rev_id in fn(rev)) yield rev if check and per_target.intersection(targets).difference([target]): raise RevisionError( "Requested revision %s overlaps with " "other requested revisions" % target.revision) def _iterate_revisions( self, upper, lower, inclusive=True, implicit_base=False): """iterate revisions from upper to lower. The traversal is depth-first within branches, and breadth-first across branches as a whole. """ requested_lowers = self.get_revisions(lower) # some complexity to accommodate an iteration where some # branches are starting from nothing, and others are starting # from a given point. Additionally, if the bottom branch # is specified using a branch identifier, then we limit operations # to just that branch. limit_to_lower_branch = \ isinstance(lower, compat.string_types) and lower.endswith('@base') uppers = util.dedupe_tuple(self.get_revisions(upper)) if not uppers and not requested_lowers: raise StopIteration() upper_ancestors = set(self._get_ancestor_nodes(uppers, check=True)) if limit_to_lower_branch: lowers = self.get_revisions(self._get_base_revisions(lower)) elif implicit_base and requested_lowers: lower_ancestors = set( self._get_ancestor_nodes(requested_lowers) ) lower_descendants = set( self._get_descendant_nodes(requested_lowers) ) base_lowers = set() candidate_lowers = upper_ancestors.\ difference(lower_ancestors).\ difference(lower_descendants) for rev in candidate_lowers: for downrev in rev._all_down_revisions: if self._revision_map[downrev] in candidate_lowers: break else: base_lowers.add(rev) lowers = base_lowers.union(requested_lowers) elif implicit_base: base_lowers = set(self.get_revisions(self._real_bases)) lowers = base_lowers.union(requested_lowers) elif not requested_lowers: lowers = set(self.get_revisions(self._real_bases)) else: lowers = requested_lowers # represents all nodes we will produce total_space = set( rev.revision for rev in upper_ancestors).intersection( rev.revision for rev in self._get_descendant_nodes(lowers, check=True) ) if not total_space: raise RangeNotAncestorError(lower, upper) # organize branch points to be consumed separately from # member nodes branch_todo = set( rev for rev in (self._revision_map[rev] for rev in total_space) if rev._is_real_branch_point and len(total_space.intersection(rev._all_nextrev)) > 1 ) # it's not possible for any "uppers" to be in branch_todo, # because the ._all_nextrev of those nodes is not in total_space #assert not branch_todo.intersection(uppers) todo = collections.deque( r for r in uppers if r.revision in total_space) # iterate for total_space being emptied out total_space_modified = True while total_space: if not total_space_modified: raise RevisionError( "Dependency resolution failed; iteration can't proceed") total_space_modified = False # when everything non-branch pending is consumed, # add to the todo any branch nodes that have no # descendants left in the queue if not todo: todo.extendleft( sorted( ( rev for rev in branch_todo if not rev._all_nextrev.intersection(total_space) ), # favor "revisioned" branch points before # dependent ones key=lambda rev: 0 if rev.is_branch_point else 1 ) ) branch_todo.difference_update(todo) # iterate nodes that are in the immediate todo while todo: rev = todo.popleft() total_space.remove(rev.revision) total_space_modified = True # do depth first for elements within branches, # don't consume any actual branch nodes todo.extendleft([ self._revision_map[downrev] for downrev in reversed(rev._all_down_revisions) if self._revision_map[downrev] not in branch_todo and downrev in total_space]) if not inclusive and rev in requested_lowers: continue yield rev assert not branch_todo class Revision(object): """Base class for revisioned objects. The :class:`.Revision` class is the base of the more public-facing :class:`.Script` object, which represents a migration script. The mechanics of revision management and traversal are encapsulated within :class:`.Revision`, while :class:`.Script` applies this logic to Python files in a version directory. """ nextrev = frozenset() """following revisions, based on down_revision only.""" _all_nextrev = frozenset() revision = None """The string revision number.""" down_revision = None """The ``down_revision`` identifier(s) within the migration script. Note that the total set of "down" revisions is down_revision + dependencies. """ dependencies = None """Additional revisions which this revision is dependent on. From a migration standpoint, these dependencies are added to the down_revision to form the full iteration. However, the separation of down_revision from "dependencies" is to assist in navigating a history that contains many branches, typically a multi-root scenario. """ branch_labels = None """Optional string/tuple of symbolic names to apply to this revision's branch""" def __init__( self, revision, down_revision, dependencies=None, branch_labels=None): self.revision = revision self.down_revision = tuple_rev_as_scalar(down_revision) self.dependencies = tuple_rev_as_scalar(dependencies) self._resolved_dependencies = () self._orig_branch_labels = util.to_tuple(branch_labels, default=()) self.branch_labels = set(self._orig_branch_labels) def __repr__(self): args = [ repr(self.revision), repr(self.down_revision) ] if self.dependencies: args.append("dependencies=%r" % self.dependencies) if self.branch_labels: args.append("branch_labels=%r" % self.branch_labels) return "%s(%s)" % ( self.__class__.__name__, ", ".join(args) ) def add_nextrev(self, revision): self._all_nextrev = self._all_nextrev.union([revision.revision]) if self.revision in revision._versioned_down_revisions: self.nextrev = self.nextrev.union([revision.revision]) @property def _all_down_revisions(self): return util.to_tuple(self.down_revision, default=()) + \ self._resolved_dependencies @property def _versioned_down_revisions(self): return util.to_tuple(self.down_revision, default=()) @property def is_head(self): """Return True if this :class:`.Revision` is a 'head' revision. This is determined based on whether any other :class:`.Script` within the :class:`.ScriptDirectory` refers to this :class:`.Script`. Multiple heads can be present. """ return not bool(self.nextrev) @property def _is_real_head(self): return not bool(self._all_nextrev) @property def is_base(self): """Return True if this :class:`.Revision` is a 'base' revision.""" return self.down_revision is None @property def _is_real_base(self): """Return True if this :class:`.Revision` is a "real" base revision, e.g. that it has no dependencies either.""" # we use self.dependencies here because this is called up # in initialization where _real_dependencies isn't set up # yet return self.down_revision is None and self.dependencies is None @property def is_branch_point(self): """Return True if this :class:`.Script` is a branch point. A branchpoint is defined as a :class:`.Script` which is referred to by more than one succeeding :class:`.Script`, that is more than one :class:`.Script` has a `down_revision` identifier pointing here. """ return len(self.nextrev) > 1 @property def _is_real_branch_point(self): """Return True if this :class:`.Script` is a 'real' branch point, taking into account dependencies as well. """ return len(self._all_nextrev) > 1 @property def is_merge_point(self): """Return True if this :class:`.Script` is a merge point.""" return len(self._versioned_down_revisions) > 1 def tuple_rev_as_scalar(rev): if not rev: return None elif len(rev) == 1: return rev[0] else: return rev PK`=]xiibase.pynu[import datetime import os import re import shutil from .. import util from ..util import compat from . import revision from ..runtime import migration from contextlib import contextmanager _sourceless_rev_file = re.compile(r'(?!__init__)(.*\.py)(c|o)?$') _only_source_rev_file = re.compile(r'(?!__init__)(.*\.py)$') _legacy_rev = re.compile(r'([a-f0-9]+)\.py$') _mod_def_re = re.compile(r'(upgrade|downgrade)_([a-z0-9]+)') _slug_re = re.compile(r'\w+') _default_file_template = "%(rev)s_%(slug)s" _split_on_space_comma = re.compile(r',|(?: +)') class ScriptDirectory(object): """Provides operations upon an Alembic script directory. This object is useful to get information as to current revisions, most notably being able to get at the "head" revision, for schemes that want to test if the current revision in the database is the most recent:: from alembic.script import ScriptDirectory from alembic.config import Config config = Config() config.set_main_option("script_location", "myapp:migrations") script = ScriptDirectory.from_config(config) head_revision = script.get_current_head() """ def __init__(self, dir, file_template=_default_file_template, truncate_slug_length=40, version_locations=None, sourceless=False, output_encoding="utf-8"): self.dir = dir self.file_template = file_template self.version_locations = version_locations self.truncate_slug_length = truncate_slug_length or 40 self.sourceless = sourceless self.output_encoding = output_encoding self.revision_map = revision.RevisionMap(self._load_revisions) if not os.access(dir, os.F_OK): raise util.CommandError("Path doesn't exist: %r. Please use " "the 'init' command to create a new " "scripts folder." % dir) @property def versions(self): loc = self._version_locations if len(loc) > 1: raise util.CommandError("Multiple version_locations present") else: return loc[0] @util.memoized_property def _version_locations(self): if self.version_locations: return [ os.path.abspath(util.coerce_resource_to_filename(location)) for location in self.version_locations ] else: return (os.path.abspath(os.path.join(self.dir, 'versions')),) def _load_revisions(self): if self.version_locations: paths = [ vers for vers in self._version_locations if os.path.exists(vers)] else: paths = [self.versions] for vers in paths: for file_ in os.listdir(vers): script = Script._from_filename(self, vers, file_) if script is None: continue yield script @classmethod def from_config(cls, config): """Produce a new :class:`.ScriptDirectory` given a :class:`.Config` instance. The :class:`.Config` need only have the ``script_location`` key present. """ script_location = config.get_main_option('script_location') if script_location is None: raise util.CommandError("No 'script_location' key " "found in configuration.") truncate_slug_length = config.get_main_option("truncate_slug_length") if truncate_slug_length is not None: truncate_slug_length = int(truncate_slug_length) version_locations = config.get_main_option("version_locations") if version_locations: version_locations = _split_on_space_comma.split(version_locations) return ScriptDirectory( util.coerce_resource_to_filename(script_location), file_template=config.get_main_option( 'file_template', _default_file_template), truncate_slug_length=truncate_slug_length, sourceless=config.get_main_option("sourceless") == "true", output_encoding=config.get_main_option("output_encoding", "utf-8"), version_locations=version_locations ) @contextmanager def _catch_revision_errors( self, ancestor=None, multiple_heads=None, start=None, end=None, resolution=None): try: yield except revision.RangeNotAncestorError as rna: if start is None: start = rna.lower if end is None: end = rna.upper if not ancestor: ancestor = ( "Requested range %(start)s:%(end)s does not refer to " "ancestor/descendant revisions along the same branch" ) ancestor = ancestor % {"start": start, "end": end} compat.raise_from_cause(util.CommandError(ancestor)) except revision.MultipleHeads as mh: if not multiple_heads: multiple_heads = ( "Multiple head revisions are present for given " "argument '%(head_arg)s'; please " "specify a specific target revision, " "'@%(head_arg)s' to " "narrow to a specific head, or 'heads' for all heads") multiple_heads = multiple_heads % { "head_arg": end or mh.argument, "heads": util.format_as_comma(mh.heads) } compat.raise_from_cause(util.CommandError(multiple_heads)) except revision.ResolutionError as re: if resolution is None: resolution = "Can't locate revision identified by '%s'" % ( re.argument ) compat.raise_from_cause(util.CommandError(resolution)) except revision.RevisionError as err: compat.raise_from_cause(util.CommandError(err.args[0])) def walk_revisions(self, base="base", head="heads"): """Iterate through all revisions. :param base: the base revision, or "base" to start from the empty revision. :param head: the head revision; defaults to "heads" to indicate all head revisions. May also be "head" to indicate a single head revision. .. versionchanged:: 0.7.0 the "head" identifier now refers to the head of a non-branched repository only; use "heads" to refer to the set of all head branches simultaneously. """ with self._catch_revision_errors(start=base, end=head): for rev in self.revision_map.iterate_revisions( head, base, inclusive=True, assert_relative_length=False): yield rev def get_revisions(self, id_): """Return the :class:`.Script` instance with the given rev identifier, symbolic name, or sequence of identifiers. .. versionadded:: 0.7.0 """ with self._catch_revision_errors(): return self.revision_map.get_revisions(id_) def get_revision(self, id_): """Return the :class:`.Script` instance with the given rev id. .. seealso:: :meth:`.ScriptDirectory.get_revisions` """ with self._catch_revision_errors(): return self.revision_map.get_revision(id_) def as_revision_number(self, id_): """Convert a symbolic revision, i.e. 'head' or 'base', into an actual revision number.""" with self._catch_revision_errors(): rev, branch_name = self.revision_map._resolve_revision_number(id_) if not rev: # convert () to None return None else: return rev[0] def iterate_revisions(self, upper, lower): """Iterate through script revisions, starting at the given upper revision identifier and ending at the lower. The traversal uses strictly the `down_revision` marker inside each migration script, so it is a requirement that upper >= lower, else you'll get nothing back. The iterator yields :class:`.Script` objects. .. seealso:: :meth:`.RevisionMap.iterate_revisions` """ return self.revision_map.iterate_revisions(upper, lower) def get_current_head(self): """Return the current head revision. If the script directory has multiple heads due to branching, an error is raised; :meth:`.ScriptDirectory.get_heads` should be preferred. :return: a string revision number. .. seealso:: :meth:`.ScriptDirectory.get_heads` """ with self._catch_revision_errors(multiple_heads=( 'The script directory has multiple heads (due to branching).' 'Please use get_heads(), or merge the branches using ' 'alembic merge.' )): return self.revision_map.get_current_head() def get_heads(self): """Return all "versioned head" revisions as strings. This is normally a list of length one, unless branches are present. The :meth:`.ScriptDirectory.get_current_head()` method can be used normally when a script directory has only one head. :return: a tuple of string revision numbers. """ return list(self.revision_map.heads) def get_base(self): """Return the "base" revision as a string. This is the revision number of the script that has a ``down_revision`` of None. If the script directory has multiple bases, an error is raised; :meth:`.ScriptDirectory.get_bases` should be preferred. """ bases = self.get_bases() if len(bases) > 1: raise util.CommandError( "The script directory has multiple bases. " "Please use get_bases().") elif bases: return bases[0] else: return None def get_bases(self): """return all "base" revisions as strings. This is the revision number of all scripts that have a ``down_revision`` of None. .. versionadded:: 0.7.0 """ return list(self.revision_map.bases) def _upgrade_revs(self, destination, current_rev): with self._catch_revision_errors( ancestor="Destination %(end)s is not a valid upgrade " "target from current head(s)", end=destination): revs = self.revision_map.iterate_revisions( destination, current_rev, implicit_base=True) revs = list(revs) return [ migration.MigrationStep.upgrade_from_script( self.revision_map, script) for script in reversed(list(revs)) ] def _downgrade_revs(self, destination, current_rev): with self._catch_revision_errors( ancestor="Destination %(end)s is not a valid downgrade " "target from current head(s)", end=destination): revs = self.revision_map.iterate_revisions( current_rev, destination) return [ migration.MigrationStep.downgrade_from_script( self.revision_map, script) for script in revs ] def _stamp_revs(self, revision, heads): with self._catch_revision_errors( multiple_heads="Multiple heads are present; please specify a " "single target revision"): heads = self.get_revisions(heads) # filter for lineage will resolve things like # branchname@base, version@base, etc. filtered_heads = self.revision_map.filter_for_lineage( heads, revision, include_dependencies=True) steps = [] dests = self.get_revisions(revision) or [None] for dest in dests: if dest is None: # dest is 'base'. Return a "delete branch" migration # for all applicable heads. steps.extend([ migration.StampStep(head.revision, None, False, True) for head in filtered_heads ]) continue elif dest in filtered_heads: # the dest is already in the version table, do nothing. continue # figure out if the dest is a descendant or an # ancestor of the selected nodes descendants = set( self.revision_map._get_descendant_nodes([dest])) ancestors = set(self.revision_map._get_ancestor_nodes([dest])) if descendants.intersection(filtered_heads): # heads are above the target, so this is a downgrade. # we can treat them as a "merge", single step. assert not ancestors.intersection(filtered_heads) todo_heads = [head.revision for head in filtered_heads] step = migration.StampStep( todo_heads, dest.revision, False, False) steps.append(step) continue elif ancestors.intersection(filtered_heads): # heads are below the target, so this is an upgrade. # we can treat them as a "merge", single step. todo_heads = [head.revision for head in filtered_heads] step = migration.StampStep( todo_heads, dest.revision, True, False) steps.append(step) continue else: # destination is in a branch not represented, # treat it as new branch step = migration.StampStep((), dest.revision, True, True) steps.append(step) continue return steps def run_env(self): """Run the script environment. This basically runs the ``env.py`` script present in the migration environment. It is called exclusively by the command functions in :mod:`alembic.command`. """ util.load_python_file(self.dir, 'env.py') @property def env_py_location(self): return os.path.abspath(os.path.join(self.dir, "env.py")) def _generate_template(self, src, dest, **kw): util.status("Generating %s" % os.path.abspath(dest), util.template_to_file, src, dest, self.output_encoding, **kw ) def _copy_file(self, src, dest): util.status("Generating %s" % os.path.abspath(dest), shutil.copy, src, dest) def _ensure_directory(self, path): path = os.path.abspath(path) if not os.path.exists(path): util.status( "Creating directory %s" % path, os.makedirs, path) def generate_revision( self, revid, message, head=None, refresh=False, splice=False, branch_labels=None, version_path=None, depends_on=None, **kw): """Generate a new revision file. This runs the ``script.py.mako`` template, given template arguments, and creates a new file. :param revid: String revision id. Typically this comes from ``alembic.util.rev_id()``. :param message: the revision message, the one passed by the -m argument to the ``revision`` command. :param head: the head revision to generate against. Defaults to the current "head" if no branches are present, else raises an exception. .. versionadded:: 0.7.0 :param splice: if True, allow the "head" version to not be an actual head; otherwise, the selected head must be a head (e.g. endpoint) revision. :param refresh: deprecated. """ if head is None: head = "head" with self._catch_revision_errors(multiple_heads=( "Multiple heads are present; please specify the head " "revision on which the new revision should be based, " "or perform a merge." )): heads = self.revision_map.get_revisions(head) if len(set(heads)) != len(heads): raise util.CommandError("Duplicate head revisions specified") create_date = datetime.datetime.now() if version_path is None: if len(self._version_locations) > 1: for head in heads: if head is not None: version_path = os.path.dirname(head.path) break else: raise util.CommandError( "Multiple version locations present, " "please specify --version-path") else: version_path = self.versions norm_path = os.path.normpath(os.path.abspath(version_path)) for vers_path in self._version_locations: if os.path.normpath(vers_path) == norm_path: break else: raise util.CommandError( "Path %s is not represented in current " "version locations" % version_path) if self.version_locations: self._ensure_directory(version_path) path = self._rev_path(version_path, revid, message, create_date) if not splice: for head in heads: if head is not None and not head.is_head: raise util.CommandError( "Revision %s is not a head revision; please specify " "--splice to create a new branch from this revision" % head.revision) if depends_on: with self._catch_revision_errors(): depends_on = [ dep if dep in rev.branch_labels # maintain branch labels else rev.revision # resolve partial revision identifiers for rev, dep in [ (self.revision_map.get_revision(dep), dep) for dep in util.to_list(depends_on) ] ] self._generate_template( os.path.join(self.dir, "script.py.mako"), path, up_revision=str(revid), down_revision=revision.tuple_rev_as_scalar( tuple(h.revision if h is not None else None for h in heads)), branch_labels=util.to_tuple(branch_labels), depends_on=revision.tuple_rev_as_scalar(depends_on), create_date=create_date, comma=util.format_as_comma, message=message if message is not None else ("empty message"), **kw ) script = Script._from_path(self, path) if branch_labels and not script.branch_labels: raise util.CommandError( "Version %s specified branch_labels %s, however the " "migration file %s does not have them; have you upgraded " "your script.py.mako to include the " "'branch_labels' section?" % ( script.revision, branch_labels, script.path )) self.revision_map.add_revision(script) return script def _rev_path(self, path, rev_id, message, create_date): slug = "_".join(_slug_re.findall(message or "")).lower() if len(slug) > self.truncate_slug_length: slug = slug[:self.truncate_slug_length].rsplit('_', 1)[0] + '_' filename = "%s.py" % ( self.file_template % { 'rev': rev_id, 'slug': slug, 'year': create_date.year, 'month': create_date.month, 'day': create_date.day, 'hour': create_date.hour, 'minute': create_date.minute, 'second': create_date.second } ) return os.path.join(path, filename) class Script(revision.Revision): """Represent a single revision file in a ``versions/`` directory. The :class:`.Script` instance is returned by methods such as :meth:`.ScriptDirectory.iterate_revisions`. """ def __init__(self, module, rev_id, path): self.module = module self.path = path super(Script, self).__init__( rev_id, module.down_revision, branch_labels=util.to_tuple( getattr(module, 'branch_labels', None), default=()), dependencies=util.to_tuple( getattr(module, 'depends_on', None), default=()) ) module = None """The Python module representing the actual script itself.""" path = None """Filesystem path of the script.""" @property def doc(self): """Return the docstring given in the script.""" return re.split("\n\n", self.longdoc)[0] @property def longdoc(self): """Return the docstring given in the script.""" doc = self.module.__doc__ if doc: if hasattr(self.module, "_alembic_source_encoding"): doc = doc.decode(self.module._alembic_source_encoding) return doc.strip() else: return "" @property def log_entry(self): entry = "Rev: %s%s%s%s\n" % ( self.revision, " (head)" if self.is_head else "", " (branchpoint)" if self.is_branch_point else "", " (mergepoint)" if self.is_merge_point else "", ) if self.is_merge_point: entry += "Merges: %s\n" % (self._format_down_revision(), ) else: entry += "Parent: %s\n" % (self._format_down_revision(), ) if self.dependencies: entry += "Also depends on: %s\n" % ( util.format_as_comma(self.dependencies)) if self.is_branch_point: entry += "Branches into: %s\n" % ( util.format_as_comma(self.nextrev)) if self.branch_labels: entry += "Branch names: %s\n" % ( util.format_as_comma(self.branch_labels), ) entry += "Path: %s\n" % (self.path,) entry += "\n%s\n" % ( "\n".join( " %s" % para for para in self.longdoc.splitlines() ) ) return entry def __str__(self): return "%s -> %s%s%s%s, %s" % ( self._format_down_revision(), self.revision, " (head)" if self.is_head else "", " (branchpoint)" if self.is_branch_point else "", " (mergepoint)" if self.is_merge_point else "", self.doc) def _head_only( self, include_branches=False, include_doc=False, include_parents=False, tree_indicators=True, head_indicators=True): text = self.revision if include_parents: if self.dependencies: text = "%s (%s) -> %s" % ( self._format_down_revision(), util.format_as_comma(self.dependencies), text ) else: text = "%s -> %s" % ( self._format_down_revision(), text) if include_branches and self.branch_labels: text += " (%s)" % util.format_as_comma(self.branch_labels) if head_indicators or tree_indicators: text += "%s%s" % ( " (head)" if self._is_real_head else "", " (effective head)" if self.is_head and not self._is_real_head else "" ) if tree_indicators: text += "%s%s" % ( " (branchpoint)" if self.is_branch_point else "", " (mergepoint)" if self.is_merge_point else "", ) if include_doc: text += ", %s" % self.doc return text def cmd_format( self, verbose, include_branches=False, include_doc=False, include_parents=False, tree_indicators=True): if verbose: return self.log_entry else: return self._head_only( include_branches, include_doc, include_parents, tree_indicators) def _format_down_revision(self): if not self.down_revision: return "" else: return util.format_as_comma(self._versioned_down_revisions) @classmethod def _from_path(cls, scriptdir, path): dir_, filename = os.path.split(path) return cls._from_filename(scriptdir, dir_, filename) @classmethod def _from_filename(cls, scriptdir, dir_, filename): if scriptdir.sourceless: py_match = _sourceless_rev_file.match(filename) else: py_match = _only_source_rev_file.match(filename) if not py_match: return None py_filename = py_match.group(1) if scriptdir.sourceless: is_c = py_match.group(2) == 'c' is_o = py_match.group(2) == 'o' else: is_c = is_o = False if is_o or is_c: py_exists = os.path.exists(os.path.join(dir_, py_filename)) pyc_exists = os.path.exists(os.path.join(dir_, py_filename + "c")) # prefer .py over .pyc because we'd like to get the # source encoding; prefer .pyc over .pyo because we'd like to # have the docstrings which a -OO file would not have if py_exists or is_o and pyc_exists: return None module = util.load_python_file(dir_, filename) if not hasattr(module, "revision"): # attempt to get the revision id from the script name, # this for legacy only m = _legacy_rev.match(filename) if not m: raise util.CommandError( "Could not determine revision id from filename %s. " "Be sure the 'revision' variable is " "declared inside the script (please see 'Upgrading " "from Alembic 0.1 to 0.2' in the documentation)." % filename) else: revision = m.group(1) else: revision = module.revision return Script(module, revision, os.path.join(dir_, filename)) PK`=]S[[ __init__.pynu[from .base import ScriptDirectory, Script # noqa __all__ = ['ScriptDirectory', 'Script'] PK`=]YY)__pycache__/revision.cpython-37.opt-1.pycnu[PK`=]ĂYY#Y__pycache__/revision.cpython-37.pycnu[PK`=]kRR__pycache__/base.cpython-37.pycnu[PK`=]-)__pycache__/__init__.cpython-37.opt-1.pycnu[PK`=]i,RR%__pycache__/base.cpython-37.opt-1.pycnu[PK`=]-#Z__pycache__/__init__.cpython-37.pycnu[PK`=]fYV'u'u >\revision.pynu[PK`=]xiibase.pynu[PK`=]S[[ ];__init__.pynu[PK 9;