minchoc

Minimal Chocolatey-compatible NuGet server in a Django app.

Installation

pip install minchoc

In settings.py, add 'minchoc' to INSTALLED_APPS. Set ALLOW_PACKAGE_DELETION to True if you want to enable this API.

INSTALLED_APPS = ['minchoc']
ALLOW_PACKAGE_DELETION = True

A DELETE call to /api/v2/package/<id>/<version> will be denied even with authentication unless ALLOW_PACKAGE_DELETION is set to True.

Add path('', include('minchoc.urls')) to your root urls.py. Example:

from django.urls import include, path
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('minchoc.urls')),
]

Run ./manage.py migrate or similar to install the database schema.

Notes

When a user is created, a NugetUser is also made. This will contain the API key for pushing. It can be viewed in admin.

Add your source to Chocolatey

As administrator:

choco source add -s 'https://your-host/url-prefix'
choco apikey add -s 'https://your-host/url-prefix' -k 'your-key'

On non-Windows platforms, you can use my pychoco package, which also supports the above commands.

Supported commands

  • choco install

  • choco push

  • choco search

Models

class minchoc.models.Author(*args, **kwargs)

Author of the software, not the NuGet spec.

exception DoesNotExist
exception MultipleObjectsReturned
class minchoc.models.Company(*args, **kwargs)

Company associated to NuGet packages.

exception DoesNotExist
exception MultipleObjectsReturned
class minchoc.models.NugetUser(*args, **kwargs)

An owner of a NuGet spec.

exception DoesNotExist
exception MultipleObjectsReturned
static request_has_valid_token(request: HttpRequest) bool

Checks if the API key in the request (header X-NuGet-ApiKey, case insensitive) is valid.

static token_exists(token: str | None) bool

Simple method to check if a token exists.

class minchoc.models.Package(*args, **kwargs)

An instance of a NuGet package.

exception DoesNotExist
exception MultipleObjectsReturned

Views

class minchoc.views.APIV2PackageView(**kwargs)
dispatch(request: HttpRequest, *args: Any, **kwargs: Any) HttpResponse

Checks if a user is authorised before allowing the request to continue.

post(request: HttpRequest) HttpResponse

A POST request is treated the same as PUT.

put(request: HttpRequest) HttpResponse

Upload a package. This must be a multipart upload with a single valid NuGet file.

minchoc.views.fetch_package_file(request: HttpRequest, name: str, version: str) HttpResponse

Get the file for a package instance.

Sample URL: /api/package/name/123.0.0

This also handles deletions. Deletions will only be allowed with authentication and with settings.ALLOW_PACKAGE_DELETION set to True.

minchoc.views.find_packages_by_id(request: HttpRequest) HttpResponse

Takes a GET request to find packages.

Sample URL: /FindPackagesById()?id=package-name

minchoc.views.home(_request: HttpRequest) HttpResponse

Static homepage.

minchoc.views.metadata(_request: HttpRequest) HttpResponse

Static page at /$metadata and at /api/v2/$metadata.

minchoc.views.packages(request: HttpRequest) HttpResponse

Takes a GET request to find packages. Query parameters $skip, $top and semVerLevel are ignored. This means pagination is currently not supported.

Sample URL: /Packages()?$orderby=id&$filter=(tolower(Id) eq 'package-name') and IsLatestVersion&$skip=0&$top=1

minchoc.views.packages_with_args(request: HttpRequest, name: str, version: str) HttpResponse

Alternate Packages() with arguments to find a single package instance.

Sample URL: /Packages(Id='name',Version='123.0.0')

Parsing

minchoc.filteryacc.parser = <ply.yacc.LRParser object>

An extremely basic parser for parsing $filter strings. Returns a Q instance.

Utilities

minchoc.utils.make_entry(host: str, package: Package, ending: str = '\n') str

Creates a package <entry> element for a package XML feed.

minchoc.utils.tag_text_or(tag: Element | None, default: str | None = None) str | None

Return text from a tag or the default value specified.

Indices and tables