Code Monkey home page Code Monkey logo

uritemplate's People

Contributors

andriyor avatar brettcannon avatar graingert avatar hugovk avatar imhoffd avatar jpotts18 avatar jwodder avatar kianmeng avatar lskillen avatar marc-portier avatar metatoaster avatar pombredanne avatar pquentin avatar pre-commit-ci[bot] avatar sigmavirus24 avatar tacaswell avatar thierryba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uritemplate's Issues

Add MatchUri method.

As shown in an example here, it would be nice given uri template to match a fully expanded uri. For example given uri template

http://localhost/weather/{state}/{city}?forecast={day}

and

http://localhost/weather/Washington/Redmond?forecast=today

to get back a dictionary

{
    'state': 'Washington',
    'city': 'Redmond',
    'day': 'today',
}

Provide an API for validating URI Templates

Hi!

Would you consider an API to validate whether a particular input was valid under RFC 6570 (or does such a thing exist already and I've missed it)?

E.g., http://example.com/dictionary/{term:1}/{term is not a valid URI Template seemingly, but I cannot see an API that complains about that -- uritemplate.URITemplate will happily truncate the end part there and consider that a template with just one field.

(Even having URITemplate do enough validation of its inputs would also work).

Full context: JSON Schema Draft 6 adds a uri-template format. I'd love to use uritemplate to implement it in jsonschema.

[bug] Templates with variables containing '/' do not expand

Description

If your template variables contain /, the expansion of the variable is an empty string.

How to reproduce

from uritemplate import URITemplate
uri = URITemplate('http://example.com/{/student/id}')
uri.expand(var_dict={'/student/id': '0'})
print(uri) # Prints: http://example.com/

However, if you remove the first / from the var_dict, you end up with a wrong value (/0 instead of 0):

uri.expand(var_dict={'student/id': '0'})
print(uri) # Prints: http://example.com//0

Environment

  • Arch Linux
  • Python 3.8.3
  • uritemplate 3.0.1

Incorrect expansion of multiple query variables

Version: 4.1.1. Platform: Fedora 37 x86_64 (though this is not platform dependant).

tl;dr: With multiple query variables, URITemplate appends a ? instead of a &. This is in violation of RFC6570 (IIUC).

Expected:

>>> URITemplate("http://example.org{?foo}{?bar}").expand(foo="this", bar="that")
'http://example.org?foo=this&bar=that'

(Second variable has a continuation.)

Actual:

>>> URITemplate("http://example.org{?foo}{?bar}").expand(foo="this", bar="that")
'http://example.org?foo=this?bar=that'

(Second variable has a question mark -- incorrect.)

See https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.8

For each defined variable in the variable-list:

o append "?" to the result string if this is the first defined value
or append "&" thereafter;

The form {&foo} is only for those templates that have a literal ?. See https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.9

Form-style query continuation, as indicated by the ampersand ("&")
operator in Level 3 and above templates, is useful for describing
optional &name=value pairs in a template that already contains a
literal query component with fixed parameters.

I can provide a patch later if required.

Potential bug/Unspecified behaviour

Let's look at a template like this:

http://example.com/dictionary/{term:1}

We have two different behaviours depending upon the value used to expand term.

>>> import uritemplate
>>> u = uritemplate.URITemplate('http://example.com/dictionary/{term:1}')
>>> u.expand(term='foo')
'http://example.com/dictionary/f'
>>> u.expand(term=['foo', 'bar', 'bogus'])
'http://example.com/dictionary/foo,bar,bogus'

A simplified version of this is simply

{term:1}

In other words:

>>> import uritemplate
>>> u = uritemplate.URITemplate('{term:1}')
>>> u.expand(term='foo')
'f'
>>> u.expand(term=['foo', 'bar', 'bogus'])
'foo,bar,bogus'

All versions of uritemplate (and uritemplate.py) exhibit this behaviour and the RFC does not provide clear guidance.

I have not investigated how other implementations in other languages handle this, though. There do not appear to be any examples in the RFC that combine lists with length limitations.

Consider adding `None` as `ScalarVariableValue`

Right now mypy flags this code is invalid:

from uritemplate import URITemplate
t = URITemplate('https://api.github.com{/end}')

t.expand({'end': None})  # error: Dict entry 0 has incompatible type "str": "None"; expected "str": "Union[Sequence[Union[int, float, complex, str]], Mapping[str, Union[int, float, complex, str]], complex]"
# Returns 'https://api.github.com'

I am not familiar with the API. Should this be allowed?
Since runtime works - I suspect that it might be worth considering.

SyntaxError: invalid syntax after recent update.

Hi guys, after the 4.0.0. or 4.0.1 update, a nested dependency (coreapi) using uritemplate without any version requirements causes the below exception.

webapp_1           | Traceback (most recent call last):
webapp_1           |   File "/srv/django/manage.py", line 19, in <module>
webapp_1           |     execute_from_command_line(sys.argv)
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
webapp_1           |     utility.execute()
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute
webapp_1           |     django.setup()
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django/__init__.py", line 27, in setup
webapp_1           |     apps.populate(settings.INSTALLED_APPS)
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
webapp_1           |     app_config = AppConfig.create(entry)
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django/apps/config.py", line 94, in create
webapp_1           |     module = import_module(entry)
webapp_1           |   File "/usr/local/lib/python2.7/importlib/__init__.py", line 37, in import_module
webapp_1           |     __import__(name)
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django_filters/__init__.py", line 7, in <module>
webapp_1           |     from .filterset import FilterSet
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django_filters/filterset.py", line 12, in <module>
webapp_1           |     from .compat import remote_field, remote_queryset
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/django_filters/compat.py", line 28, in <module>
webapp_1           |     import coreapi
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/coreapi/__init__.py", line 2, in <module>
webapp_1           |     from coreapi import auth, codecs, exceptions, transports, utils
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/coreapi/transports/__init__.py", line 3, in <module>
webapp_1           |     from coreapi.transports.http import HTTPTransport
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/coreapi/transports/http.py", line 13, in <module>
webapp_1           |     import uritemplate
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/uritemplate/__init__.py", line 28, in <module>
webapp_1           |     from uritemplate.api import (
webapp_1           |   File "/usr/local/lib/python2.7/site-packages/uritemplate/api.py", line 19
webapp_1           |     uri: str,
webapp_1           |        ^
webapp_1           | SyntaxError: invalid syntax

I pinned the version to 3.0.1 to get around the issue.

uritemplate == 3.0.1

I realise this issue might not be in the right place, as this might be incorrect usage in coreapi (outside of not pinning the version to the right major version), but I guess other people might run into the same thing.

Best regards

What about matching?

i.e. given a URI and a template? does the URI match the template?
This would be a useful feature

Version 4.1.0 is incompatible with Python 2

In setup.cfg you are claiming that the newest version should work on Python 2 which is not true. Currently pip in Python 2 allows installing 4.1.0. Noticed this in our CI pipelines as we're installing django-rest-swagger==2.1.2 which has uritemplate (any version) as dependency.

>>> from uritemplate.api import (URITemplate, expand, partial, variables)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/julius/.virtualenvs/pcloud/lib/python2.7/site-packages/uritemplate/__init__.py", line 28, in <module>
    from uritemplate.api import (
  File "/Users/julius/.virtualenvs/pcloud/lib/python2.7/site-packages/uritemplate/api.py", line 19
    uri: str,
       ^
SyntaxError: invalid syntax

Installation instructions to provide `uri-template; extra == "format"`

A downstream package which uses jsonschema gives me the following error when I try to run it:

Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.9/dandi", line 33, in <module>
    sys.exit(load_entry_point('dandi==0+unknown', 'console_scripts', 'dandi')())
  File "/usr/lib/python-exec/python3.9/dandi", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/usr/lib/python3.9/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/usr/lib/python3.9/site-packages/dandi/cli/command.py", line 18, in <module>
    from ..utils import get_module_version
  File "/usr/lib/python3.9/site-packages/dandi/utils.py", line 25, in <module>
    import requests
  File "/usr/lib/python3.9/site-packages/requests/__init__.py", line 133, in <module>
    from . import utils
  File "/usr/lib/python3.9/site-packages/requests/utils.py", line 27, in <module>
    from . import certs
  File "/usr/lib/python3.9/site-packages/requests/certs.py", line 15, in <module>
    from certifi import where
  File "/usr/lib/python3.9/site-packages/certifi/__init__.py", line 1, in <module>
    from .core import contents, where
  File "/usr/lib/python3.9/site-packages/certifi/core.py", line 3, in <module>
    from certifi._patch import _verify_dist_info
  File "/usr/lib/python3.9/site-packages/certifi/_patch.py", line 4, in <module>
    import pkg_resources
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3267, in <module>
    def _initialize_master_working_set():
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3241, in _call_aside
    f(*args, **kwargs)
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3279, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 573, in _build_master
    ws.require(__requires__)
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 891, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 777, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'uri-template; extra == "format"' distribution was not found and is required by jsonschema

Any idea what uritemplate install instructions are needed in order to fulfill this requirement?

Incorrect Reserved Expansion

Valid UTF-8-percent-encoded code points must be preserved in reserved expansion. This implementation (Version: 4.1.1) fails the following test from https://github.com/uri-templates/uritemplate-test/blob/master/extended-tests.json:

{
  ...
  "Additional Examples 6: Reserved Expansion": {
    "variables" : {
      "id" : "admin%2F",
      ...
  },
  "testcases": [
    ["{+id}", "admin%2F"],
    ...
  ]
}

The correct/expected expansion is 'admin%2F', the actual expansion is 'admin%252F':

>>> from uritemplate import URITemplate, expand
>>> URITemplate('{+id}').expand(id='admin%2F')
'admin%252F'
>>> expand('{+id}', id='admin%2F')
'admin%252F'

Add method to parse template

Currently urlparse can do this for semi-normal URIs that happen to be templates. Try for example parsing both of the following URIs

  • https://{server}/{path}
  • https://{server}{/path}

The first is handled fine, the second is parsed as: ('https', '{server}{', 'path}', '', '', '')

Properly parsing this could be useful and is born out of a desire to see how challenging it would be rather than a need for it.

[BUG] Non-string var values aren't truly supported

I saw #17 that claimed that int/float vals should be supported and #20 that fixed it back in 2015. Imagine my surprise when I see that removed check in the traceback on passing int.

Looks like there's a similar place in code that hasn't been fixed for some reason and still causes trouble: https://github.com/python-hyper/uritemplate/blob/3.0.1/uritemplate/variable.py#L194

$ ipython
Python 3.7.1 (default, Jan 28 2019, 08:25:13) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import uritemplate                                                         

In [2]: uritemplate.URITemplate('/test{/num}').expand({'num': 3})                  
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-5afe50171000> in <module>
----> 1 uritemplate.URITemplate('/test{/num}').expand({'num': 3})

~/.pyenv/versions/3.7.1/lib/python3.7/site-packages/uritemplate/template.py in expand(self, var_dict, **kwargs)
    130 
    131         """
--> 132         return self._expand(_merge(var_dict, kwargs), False)
    133 
    134     def partial(self, var_dict=None, **kwargs):

~/.pyenv/versions/3.7.1/lib/python3.7/site-packages/uritemplate/template.py in _expand(self, var_dict, replace)
     95         expanded = {}
     96         for v in self.variables:
---> 97             expanded.update(v.expand(expansion))
     98 
     99         def replace_all(match):

~/.pyenv/versions/3.7.1/lib/python3.7/site-packages/uritemplate/variable.py in expand(self, var_dict)
    336                 expansion = self._string_expansion
    337 
--> 338             expanded = expansion(name, value, opts['explode'], opts['prefix'])
    339 
    340             if expanded is not None:

~/.pyenv/versions/3.7.1/lib/python3.7/site-packages/uritemplate/variable.py in _label_path_expansion(self, name, value, explode, prefix)
    188         safe = self.safe
    189 
--> 190         if value is None or (len(value) == 0 and value != ''):
    191             return None
    192 

TypeError: object of type 'int' has no len()

Examples

Not knowing this was inspired by an RFC, I was having a hard time finding some examples, eventually digging into the source to see how I could get foo/bar expanded into {/path}. A short list of examples wouldn't go amiss. Neither would a link to the RFC I guess ๐Ÿ˜„

Package uploaded to wrong index

There are two separate packages/projects with the name uritemplate, one is "uritemplate", the other is "uritemplate.py". It seems you are an index owner on both

On 8/20/16, a package from uritemplate.py was uploaded to the other project's index.
This project: https://pypi.python.org/pypi/uritemplate.py/2.0.0
Clobbered this project: https://pypi.python.org/pypi/uritemplate/0.6
With this pre-release version: https://pypi.python.org/pypi/uritemplate/2.0.0rc1

Can you remove the 2.0.0rc1 package from the other project please?

Thanks,

New release?

Looks like there have been a few changes since the last release (in 2013 ๐Ÿ˜ณ) particularly from last year. Is it worthwhile to cut a new release to get those out? ๐Ÿ˜‰

Variable names are not validated

The RFC limits the characters allowed in variables names, but there is no validation enforcing this.

From ยง 2.3:

 variable-list =  varspec *( "," varspec )
 varspec       =  varname [ modifier-level4 ]
 varname       =  varchar *( ["."] varchar )
 varchar       =  ALPHA / DIGIT / "_" / pct-encoded

(I'm not opposed to expanding the set of allowed characters.)

Resolve DeprecatioWarning for import of ABCs from 'collections' instead of 'collections.abc'

Seeing this deprecation warning when running a test suite that depends on uritemplate:

  /home/myusername/venv/lib64/python3.7/site-packages/uritemplate/variable.py:363: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
    return isinstance(value, (dict, collections.MutableMapping))

objct of type int has no len()

I get this error when I run the read me after pip installing uritemplate.py

I am running python 2.7.5

Traceback (most recent call last):
  File "sandbox.py", line 5, in <module>
    print(t.expand(gist_id=123456))
  File "/Users/jpotts18/.virtualenvs/parakeet_env/lib/python2.7/site-packages/uritemplate/template.py", line 127, in expand
    return self._expand(var_dict, False)
  File "/Users/jpotts18/.virtualenvs/parakeet_env/lib/python2.7/site-packages/uritemplate/template.py", line 89, in _expand
    expanded.update(v.expand(expansion))
  File "/Users/jpotts18/.virtualenvs/parakeet_env/lib/python2.7/site-packages/uritemplate/variable.py", line 333, in expand
    expanded = expansion(name, value, opts['explode'], opts['prefix'])
  File "/Users/jpotts18/.virtualenvs/parakeet_env/lib/python2.7/site-packages/uritemplate/variable.py", line 185, in _label_path_expansion
    if value is None or (len(value) == 0 and value != ''):
TypeError: object of type 'int' has no len()

Default values

I noticed the implementation allows specifying default values in the template, which is cool, but is not supported by the RFC.

Maybe this feature should be added to the RFC?

"uritemplate.py" conflicts with "uritemplate" package

There is a package called uritemplate on the PyPI whose name conflicts with this package. Both packages require you to import uritemplate.

I ran into this issue because our project requires both github3.py (which depends on uritemplate.py) and google-python-api-client (which depends on uritemplate), which led to the following error:

from uritemplate import URITemplate
ImportError: cannot import name URITemplate

I'm not sure what the best solution for this would be. Just thought I'd report it for record-keeping and to see if anyone had any workarounds.

repo and pypi confusion

@sigmavirus24, I like this project a lot. I noticed it's used by the Google API module for Python, so I took a look. I had just implemented a very limited version of URI templates for a requests-based project I've been working on. I didn't know anything about this project or the RFC upon which it's based. When my time allows, I'd like to contribute to this project, if you'd welcome my help.

I have a few questions, though (maybe some of which you'd like help resolving):

  • Which git repo should be used, this GitHub one or the one on Bitbucket? I presume this one should be, since it's the most recently updated and it has the highest version number in the code. (Should the Bitbucket repo be closed or turned into a mirror of this one? Maybe remove the link to Bitbucket from the README, too.)
  • PyPI has two entries for uritemplate packages:
    • uritemplate 3.0.0 - Which appears to be this project.
    • uritemplate.py 3.0.2 - Despite the newer version number in the name, it appears to be older. I downloaded it and found that __init__.py contains a vesion of "2.0.0".
  • What do you think of giving the project another name? "uritemplate" is a too generic. From another Bitbucket repo of the same name, I found it referred to a "uri-templates" project on Google Code. Google Code linked to a GitHub repo named "uritemplates/uritemplate-py", which is maintained by three of the authors of the RFC. However, the README in that repo links to the PyPI package that happens to be... this project! Not to mention that there are similar projects for other programming languages with similar names. Maybe it's time to pick a totally different name and carry on from there. (I hear "Eric" is a nice name. ๐Ÿ˜‰)
  • The documentation is confusing. The docs linked from the README appear to be very old. Maybe a better solution would be to set up a documentation site with github.io to consolidate everything around GitHub.
  • The history document shows that the 3.* versions are less recent than 2.0.0. 3.* is also from 2015, but 2.0.0 is from 2016.

My apologies for dumping a bunch of things in this one message. I hope I don't seem to be complaining. I have a lot of respect for your contributions to flake8 and requests and this project seems to meet an important need, IMHO. I'd really like to contribute, so maybe these are things I could help with in addition to coding.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.