mirror of
https://github.com/boostorg/website-v2.git
synced 2026-02-27 05:32:08 +00:00
Merge pull request #105 from revsys/version-library-m2m
Add a ManyToMany on Library to Version
This commit is contained in:
16
README.md
16
README.md
@@ -104,6 +104,22 @@ For production, execute:
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
## Generating Fake Data
|
||||
|
||||
### Versions and LibraryVersions
|
||||
|
||||
First, make sure your `GITHUB_TOKEN` is set in you `.env` file and run `./manage.py update_libraries`. This takes a long time. See below.
|
||||
|
||||
Run `./manage.py generate_fake_versions`. This will create 50 active Versions, and associate Libraries to them.
|
||||
|
||||
The data created is realistic-looking in that each Library will contain a M2M relationship to every Version newer than the oldest one it's included in. (So if a Library's earliest LibraryVersion is 1.56.0, then there will be a LibraryVersion object for that Library for each Version since 1.56.0 was released.)
|
||||
|
||||
This does not add VersionFile objects to the Versions.
|
||||
|
||||
### Libraries, Pull Requests, and Issues
|
||||
|
||||
There is not currently a way to generate fake Libraries, Issues, or Pull Requests. To generate those, use your GitHub token and run `./manage.py update_libraries` locally to pull in live GitHub data. This command takes a long time to run; you might consider editing `libraries/github.py` to add counters and breaks to shorten the runtime.
|
||||
|
||||
## Deploying
|
||||
|
||||
TDB
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Category, Issue, Library, PullRequest
|
||||
from .models import Category, Issue, Library, LibraryVersion, PullRequest
|
||||
|
||||
|
||||
@admin.register(Category)
|
||||
@@ -26,6 +26,13 @@ class LibraryAdmin(admin.ModelAdmin):
|
||||
return obj.active_development
|
||||
|
||||
|
||||
@admin.register(LibraryVersion)
|
||||
class LibraryVersionAdmin(admin.ModelAdmin):
|
||||
list_display = ["library", "version"]
|
||||
list_filter = ["library", "version"]
|
||||
search_fields = ["library__name", "version__name"]
|
||||
|
||||
|
||||
@admin.register(Issue)
|
||||
class IssueAdmin(admin.ModelAdmin):
|
||||
list_display = ["title", "number", "is_open", "closed"]
|
||||
|
||||
55
libraries/management/commands/generate_fake_versions.py
Normal file
55
libraries/management/commands/generate_fake_versions.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import djclick as click
|
||||
import random
|
||||
|
||||
from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
from faker import Faker
|
||||
|
||||
from libraries.models import Library, LibraryVersion
|
||||
from versions.models import Version
|
||||
|
||||
fake = Faker()
|
||||
|
||||
|
||||
@click.command()
|
||||
def command():
|
||||
"""
|
||||
Create Version objects and attach libraries to them.
|
||||
"""
|
||||
|
||||
# Create versions
|
||||
release_date = timezone.now() - timedelta(days=3650)
|
||||
for i in range(30, 80):
|
||||
version, created = Version.objects.get_or_create(
|
||||
name=f"1.{i}.0",
|
||||
defaults={
|
||||
"release_date": release_date,
|
||||
"description": fake.paragraph(nb_sentences=2),
|
||||
"active": True,
|
||||
},
|
||||
)
|
||||
if created:
|
||||
click.secho(f"Version {version.name} created succcessfully", fg="green")
|
||||
else:
|
||||
click.secho(f"Version {version.name} already exists.")
|
||||
|
||||
delta = random.choice(range(20, 50))
|
||||
release_date += timedelta(delta)
|
||||
|
||||
for library in Library.objects.all():
|
||||
# Select the starting version randomly
|
||||
start_version = Version.objects.order_by("?").first()
|
||||
|
||||
# Add a LibraryVersion for each Version newer than the starting version
|
||||
for version in Version.objects.filter(
|
||||
release_date__gt=start_version.release_date
|
||||
):
|
||||
lib_version, created = LibraryVersion.objects.get_or_create(
|
||||
library=library, version=version
|
||||
)
|
||||
if created:
|
||||
click.secho(f"---{lib_version} created succcessfully", fg="green")
|
||||
else:
|
||||
click.secho(f"LibraryVersion {lib_version} already exists.")
|
||||
|
||||
click.secho("All done!", fg="green")
|
||||
56
libraries/migrations/0004_auto_20230130_1830.py
Normal file
56
libraries/migrations/0004_auto_20230130_1830.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# Generated by Django 3.2.2 on 2023-01-30 18:30
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("versions", "0005_version_active"),
|
||||
("libraries", "0003_library_slug"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="LibraryVersion",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"library",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="library_version",
|
||||
to="libraries.library",
|
||||
),
|
||||
),
|
||||
(
|
||||
"version",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="library_version",
|
||||
to="versions.version",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="library",
|
||||
name="versions",
|
||||
field=models.ManyToManyField(
|
||||
related_name="libraries",
|
||||
through="libraries.LibraryVersion",
|
||||
to="versions.Version",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -43,6 +43,9 @@ class Library(models.Model):
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
versions = models.ManyToManyField(
|
||||
"versions.Version", through="libraries.LibraryVersion", related_name="libraries"
|
||||
)
|
||||
cpp_standard_minimum = models.CharField(max_length=50, blank=True, null=True)
|
||||
|
||||
active_development = models.BooleanField(default=True, db_index=True)
|
||||
@@ -89,6 +92,24 @@ class Library(models.Model):
|
||||
return self.github_properties()["repo"]
|
||||
|
||||
|
||||
class LibraryVersion(models.Model):
|
||||
version = models.ForeignKey(
|
||||
"versions.Version",
|
||||
related_name="library_version",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
)
|
||||
library = models.ForeignKey(
|
||||
"libraries.Library",
|
||||
related_name="library_version",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.library.name} ({self.version.name})"
|
||||
|
||||
|
||||
class Issue(models.Model):
|
||||
"""
|
||||
Model that tracks Library repository issues in Github
|
||||
|
||||
@@ -18,6 +18,21 @@ def library(db):
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def library_version(library, version):
|
||||
return baker.make("libraries.LibraryVersion", library=library, version=version)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def issue(library):
|
||||
return baker.make("libraries.Issue", library=library)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pull_request(library):
|
||||
return baker.make("libraries.PullRequest", library=library)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def github_api_get_ref_response(db):
|
||||
"""Returns a JSON example of GhApi().api.git.get_ref(owner=owner, repo=repo, ref=ref)"""
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
def test_github_properties(library):
|
||||
properties = library.github_properties()
|
||||
assert properties["owner"] == "boostorg"
|
||||
@@ -10,3 +13,44 @@ def test_github_owner(library):
|
||||
|
||||
def test_github_repo(library):
|
||||
assert library.github_repo == "multi_array"
|
||||
|
||||
|
||||
def test_category_creation(category):
|
||||
assert category.name is not None
|
||||
|
||||
|
||||
def test_library_creation(library):
|
||||
assert library.versions.count() == 0
|
||||
|
||||
|
||||
def test_issue_creation(issue, library):
|
||||
assert issue.library == library
|
||||
|
||||
|
||||
def test_pull_request_creation(pull_request, library):
|
||||
assert pull_request.library == library
|
||||
|
||||
|
||||
def test_library_version_creation(library_version, library, version):
|
||||
assert library_version.library == library
|
||||
assert library_version.version == version
|
||||
|
||||
|
||||
def test_library_version_str(library_version, library, version):
|
||||
assert str(library_version) == f"{library.name} ({version.name})"
|
||||
|
||||
|
||||
def test_library_version_multiple_versions(library, library_version):
|
||||
assert library.versions.count() == 1
|
||||
assert library.versions.filter(
|
||||
library_version__version=library_version.version
|
||||
).exists()
|
||||
other_version = baker.make("versions.Version")
|
||||
new_library_version = baker.make(
|
||||
"libraries.LibraryVersion", library=library, version=other_version
|
||||
)
|
||||
assert library.versions.count() == 2
|
||||
assert library.versions.filter(
|
||||
library_version__version=library_version.version
|
||||
).exists()
|
||||
assert library.versions.filter(library_version__version=other_version).exists()
|
||||
|
||||
Reference in New Issue
Block a user