SVN URL Parser - libvcs.url.svn

For svn, aka svn(1).

Detect, parse, and validate SVN (Subversion) URLs.

Note

Subversion isn’t seen as often these days, can you “rage against the dying of the light” and assure its light is not extinguished? Help assure SVN URL parsing is correct and robust. Visit the project tracker and give us a wave. This API won’t be stabilized until we’re confident Subversion is covered accurately and can handle all-terrain scenarios.

libvcs.url.svn.DEFAULT_RULES: list[Rule] = [Rule(label=core-svn, description=Vanilla svn pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        file|http|https|svn|svn\\+ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n    (:(?P<port>\\d{1,5}), re.VERBOSE), defaults={}), Rule(label=core-svn-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'svn'})]

Core regular expressions. These are patterns understood by svn(1)

libvcs.url.svn.PIP_DEFAULT_RULES: list[Rule] = [Rule(label=pip-url, description=pip-style svn URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        svn\\+ssh|\n        svn\\+https|\n        svn\\+http\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n , re.VERBOSE), defaults={}, is_explicit=True), Rule(label=pip-file-url, description=pip-style svn+file:// URL, pattern=re.compile('\n        (?P<scheme>svn\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)]

pip-style svn URLs.

Examples of PIP-style svn URLs (via pip.pypa.io):

MyProject @ svn+https://svn.example.com/MyProject
MyProject @ svn+ssh://svn.example.com/MyProject
MyProject @ svn+ssh://user@svn.example.com/MyProject

Refs (via pip.pypa.io):

MyProject @ -e svn+http://svn.example.com/svn/MyProject/trunk@2019
MyProject @ -e svn+http://svn.example.com/svn/MyProject/trunk@{20080101}

Notes

class libvcs.url.svn.SvnBaseURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', ref=None, rule=None)[source]

Bases: URLProtocol, SkipDefaultFieldsReprMixin

SVN repository location. Parses URLs on initialization.

Examples

>>> SvnBaseURL(
...     url='svn+ssh://svn.debian.org/svn/aliothproj/path/in/project/repository')
SvnBaseURL(url=svn+ssh://svn.debian.org/svn/aliothproj/path/in/project/repository,
       scheme=svn+ssh,
       hostname=svn.debian.org,
       path=svn/aliothproj/path/in/project/repository,
       rule=core-svn)
>>> myrepo = SvnBaseURL(
...     url='svn+ssh://svn.debian.org/svn/aliothproj/path/in/project/repository'
... )
>>> myrepo.hostname
'svn.debian.org'
>>> myrepo.path
'svn/aliothproj/path/in/project/repository'
Parameters:
  • url (str)

  • scheme (str | None)

  • user (str | None)

  • hostname (str)

  • port (int | None)

  • separator (str)

  • path (str)

  • ref (str | None)

  • rule (str | None)

rule

name of the Rule

Type:

str

url: str
scheme: Optional[str] = None
user: Optional[str] = None
hostname: str = ''
port: Optional[int] = None
separator: str = '/'
path: str = ''
ref: Optional[str] = None
rule: Optional[str] = None
rule_map = RuleMap(_rule_map={'core-svn': Rule(label=core-svn, description=Vanilla svn pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        file|http|https|svn|svn\\+ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n    (:(?P<port>\\d{1,5}), re.VERBOSE), defaults={}), 'core-svn-scp': Rule(label=core-svn-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'svn'})})
classmethod is_valid(url, is_explicit=None)[source]

Whether URL is compatible with VCS or not.

Return type:

bool

Parameters:
  • url (str)

  • is_explicit (bool | None)

Examples

>>> SvnBaseURL.is_valid(
...     url='svn+ssh://svn.debian.org/svn/aliothproj/path/in/project/repository'
... )
True
>>> SvnBaseURL.is_valid(url='notaurl')
False
to_url()[source]

Return a svn(1)-compatible URL. Can be used with svn checkout.

Return type:

str

Examples

>>> svn_url = SvnBaseURL(
...     url='svn+ssh://my-username@my-server/vcs-python/libvcs'
... )
>>> svn_url
SvnBaseURL(url=svn+ssh://my-username@my-server/vcs-python/libvcs,
        scheme=svn+ssh,
        user=my-username,
        hostname=my-server,
        path=vcs-python/libvcs,
        rule=core-svn)

Switch repo libvcs -> vcspull:

>>> svn_url.path = 'vcs-python/vcspull'
>>> svn_url.to_url()
'svn+ssh://my-username@my-server/vcs-python/vcspull'

Switch user to “tom”:

>>> svn_url.user = 'tom'
>>> svn_url.to_url()
'svn+ssh://tom@my-server/vcs-python/vcspull'
_abc_impl = <_abc._abc_data object>
_is_protocol = False
class libvcs.url.svn.SvnPipURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', ref=None, rule=None, rev=None)[source]

Bases: SvnBaseURL, URLProtocol, SkipDefaultFieldsReprMixin

Supports pip svn URLs.

Parameters:
  • url (str)

  • scheme (str | None)

  • user (str | None)

  • hostname (str)

  • port (int | None)

  • separator (str)

  • path (str)

  • ref (str | None)

  • rule (str | None)

  • rev (str | None)

rev: Optional[str] = None
rule_map = RuleMap(_rule_map={'pip-url': Rule(label=pip-url, description=pip-style svn URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        svn\\+ssh|\n        svn\\+https|\n        svn\\+http\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n , re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style svn+file:// URL, pattern=re.compile('\n        (?P<scheme>svn\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)})
classmethod is_valid(url, is_explicit=None)[source]

Whether URL is compatible with VCS or not.

Return type:

bool

Parameters:
  • url (str)

  • is_explicit (bool | None)

Examples

>>> SvnPipURL.is_valid(
...     url='svn+https://svn.project.org/project-central'
... )
True
>>> SvnPipURL.is_valid(url='svn+ssh://[email protected]:cpython')
True
>>> SvnPipURL.is_valid(url='notaurl')
False
to_url()[source]

Return a svn(1)-compatible URL. Can be used with svn clone.

Return type:

str

Examples

>>> svn_url = SvnPipURL(url='svn+https://svn.project.org/project-central')
>>> svn_url
SvnPipURL(url=svn+https://svn.project.org/project-central,
        scheme=svn+https,
        hostname=svn.project.org,
        path=project-central,
        rule=pip-url)

Switch repo project-central -> mobile-browser:

>>> svn_url.path = 'mobile-browser'
>>> svn_url.to_url()
'svn+https://svn.project.org/mobile-browser'

Switch them to localhost:

>>> svn_url.hostname = 'localhost'
>>> svn_url.scheme = 'http'
>>> svn_url.to_url()
'http://localhost/mobile-browser'
_abc_impl = <_abc._abc_data object>
_is_protocol = False
class libvcs.url.svn.SvnURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', ref=None, rule=None, rev=None)[source]

Bases: SvnPipURL, SvnBaseURL, URLProtocol, SkipDefaultFieldsReprMixin

Batteries included URL Parser. Supports svn(1) and pip URLs.

Ancestors (MRO) This URL parser inherits methods and attributes from the following parsers:

Parameters:
  • url (str)

  • scheme (str | None)

  • user (str | None)

  • hostname (str)

  • port (int | None)

  • separator (str)

  • path (str)

  • ref (str | None)

  • rule (str | None)

  • rev (str | None)

rule_map = RuleMap(_rule_map={'core-svn': Rule(label=core-svn, description=Vanilla svn pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        file|http|https|svn|svn\\+ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n    (:(?P<port>\\d{1,5}), re.VERBOSE), defaults={}), 'core-svn-scp': Rule(label=core-svn-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'svn'}), 'pip-url': Rule(label=pip-url, description=pip-style svn URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        svn\\+ssh|\n        svn\\+https|\n        svn\\+http\n      )\n    )\n\n        ://\n        \n    ((?P<user>[^/:@]+)@)?\n    (?P<hostname>([^/:@]+))\n , re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style svn+file:// URL, pattern=re.compile('\n        (?P<scheme>svn\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)})
_abc_impl = <_abc._abc_data object>
_is_protocol = False
classmethod is_valid(url, is_explicit=None)[source]

Whether URL is compatible included Svn URL rule_map or not.

Return type:

bool

Parameters:
  • url (str)

  • is_explicit (bool | None)

Examples

Will match normal svn(1) URLs, use SvnURL.is_valid() for that.

>>> SvnURL.is_valid(
... url='https://svn.project.org/project-central/project-central')
True
>>> SvnURL.is_valid(url='[email protected]:MyProject/project')
True

Pip-style URLs:

>>> SvnURL.is_valid(url='svn+https://svn.project.org/project-central/project')
True
>>> SvnURL.is_valid(url='svn+ssh://[email protected]:MyProject/project')
True
>>> SvnURL.is_valid(url='notaurl')
False

Explicit VCS detection

Pip-style URLs are prefixed with the VCS name in front, so its rule_map can unambiguously narrow the type of VCS:

>>> SvnURL.is_valid(
...     url='svn+ssh://[email protected]:project-central/image',
...     is_explicit=True
... )
True

Below, while it’s svn.project.org, that doesn’t necessarily mean that the URL itself is conclusively a svn URL (e.g. the pattern is too broad):

>>> SvnURL.is_valid(
...     url='[email protected]:project-central/image', is_explicit=True
... )
False

You could create a project rule that consider svn.project.org hostnames to be exclusively svn:

>>> projectRule = Rule(
...     # Since svn.project.org exclusively serves svn repos, make explicit
...     label='project-rule',
...     description='Matches svn.project.org https URLs, exact VCS match',
...     pattern=re.compile(
...         rf'''
...         ^(?P<scheme>ssh)?
...         ((?P<user>\w+)@)?
...         (?P<hostname>(svn.project.org)+):
...         (?P<path>(\w[^:]+))
...         ''',
...         re.VERBOSE,
...     ),
...     is_explicit=True,
...     defaults={
...         'hostname': 'svn.project.org'
...     }
... )
>>> SvnURL.rule_map.register(projectRule)
>>> SvnURL.is_valid(
...     url='[email protected]:project-central/image', is_explicit=True
... )
True
>>> SvnURL(url='[email protected]:project-central/image').rule
'project-rule'

This is just us cleaning up:

>>> SvnURL.rule_map.unregister('project-rule')
>>> SvnURL(url='[email protected]:project-central/project-rule').rule
'core-svn-scp'
to_url()[source]

Return a svn(1)-compatible URL. Can be used with svn clone.

Return type:

str

Examples

SSH style URL:

>>> svn_url = SvnURL(url='[email protected]:project-central/browser')
>>> svn_url.path = 'project-central/gfx'
>>> svn_url.to_url()
'[email protected]:project-central/gfx'

HTTPs URL:

>>> svn_url = SvnURL(url='https://svn.project.org/project-central/memory')
>>> svn_url.path = 'project-central/image'
>>> svn_url.to_url()
'https://svn.project.org/project-central/image'

Switch them to svnlab:

>>> svn_url.hostname = 'localhost'
>>> svn_url.scheme = 'http'
>>> svn_url.to_url()
'http://localhost/project-central/image'

Pip style URL, thanks to this class implementing SvnPipURL:

>>> svn_url = SvnURL(url='svn+ssh://[email protected]/project-central/image')
>>> svn_url.hostname = 'localhost'
>>> svn_url.to_url()
'svn+ssh://svn@localhost/project-central/image'
>>> svn_url.user = None
>>> svn_url.to_url()
'svn+ssh://localhost/project-central/image'