Skip to content
Snippets Groups Projects
Commit 28e4a29a authored by Tore.Brede's avatar Tore.Brede
Browse files

Merge branch 'master' into GREG-41_footer

parents 23c2d8c2 104e7268
No related branches found
No related tags found
1 merge request!53GREG-41: Initial footer and header
Showing
with 391 additions and 19 deletions
......@@ -6,6 +6,8 @@
"language": {
"change": "Change language to {{lang}}"
},
"loading": "Loading..."
},
"termsHeader": "Terms",
"staging": "Staging"
}
......@@ -6,6 +6,8 @@
"language": {
"change": "Bytt språk til {{lang}}"
},
"loading": "Laster..."
},
"termsHeader": "Vilkår",
"staging": "Staging"
}
......@@ -6,6 +6,8 @@
"language": {
"change": "Bytt språk til {{lang}}"
},
"loading": "Lastar..."
},
"termsHeader": "Vilkår",
"staging": "Staging"
}
......@@ -3,7 +3,8 @@ import { useTranslation } from 'react-i18next'
import './App.css'
import { Button } from './components/button'
import { Button } from 'components/button'
import Loading from 'components/loading'
import { appTimezone, appVersion, appTheme } from './appConfig'
import Link from './components/link'
......@@ -55,6 +56,7 @@ const App = () => {
lang: i18n.language === 'en' ? 'Norsk' : 'Engelsk',
})}
</Button>
<Loading />
<p>
Version {appVersion}
<br />
......
import styled from 'styled-components/macro'
const Spinner = styled.div`
position: relative;
display: inline-block;
width: 1.5rem;
height: 1.5rem;
margin-left: 0;
margin-right: 1rem;
margin-top: 0;
border: 3px solid rgba(200, 200, 200);
border-width: 3px;
border-radius: 50%;
border-top-color: rgba(50, 50, 50);
animation: spin 0.8s linear infinite;
@keyframes spin {
to {
transform: rotate(360deg);
}
}
`
export default Spinner
import styled, { DefaultTheme } from 'styled-components/macro'
import styled from 'styled-components/macro'
type ButtonProps = {
theme: DefaultTheme
}
export const Button = styled.a<ButtonProps>`
export const Button = styled.a`
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
......@@ -14,8 +10,8 @@ export const Button = styled.a<ButtonProps>`
color: white;
border: 2px solid white;
:hover {
background: ${(props) => props.theme.colors.secondary};
background: ${({ theme }) => theme.colors.secondary};
color: black;
}
background: ${(props) => props.theme.colors.main};
background: ${({ theme }) => theme.colors.main};
`
import React from 'react'
import { useTranslation } from 'react-i18next'
import Spinner from 'components/animations/spinner'
import styled from 'styled-components/macro'
const SpinnerWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
`
function Loading() {
const { t } = useTranslation(['common'])
return (
<SpinnerWrapper>
<Spinner />
{t('common:loading')}
</SpinnerWrapper>
)
}
export default Loading
import React, { Suspense } from 'react'
import ReactDOM from 'react-dom'
import { ThemeProvider } from 'styled-components/macro'
import 'i18n'
import getCurrentTheme from 'theme'
import GlobalStyle from 'globalStyles'
import App from './App'
import reportWebVitals from './reportWebVitals'
import Loading from 'components/loading'
function appRoot() {
return (
<>
<React.StrictMode>
<GlobalStyle />
<Suspense fallback="loading">
<Suspense fallback={<Loading />}>
<ThemeProvider theme={getCurrentTheme()}>
<App />
</ThemeProvider>
......
import { DefaultTheme } from 'styled-components'
import { DefaultTheme } from 'styled-components/macro'
const white = '#FFFFFF'
const hotPink = '#FF69B4'
......
......@@ -78,7 +78,7 @@ class ConsentAdmin(VersionAdmin):
get_consent_type_name.short_description = "Consent name" # type: ignore
class ConsentTypeAdmin(admin.ModelAdmin):
class ConsentTypeAdmin(VersionAdmin):
list_display = (
"id",
"name_en",
......@@ -90,8 +90,9 @@ class ConsentTypeAdmin(admin.ModelAdmin):
class OrganizationalUnitAdmin(VersionAdmin):
list_display = ("id", "name_en", "parent")
list_display = ("id", "orgreg_id", "name_en", "parent")
readonly_fields = ("id", "created", "updated")
search_fields = ("name_en", "id", "orgreg_id")
class OrganizationalUnitInline(admin.TabularInline):
......
"""
Fetch all OUs from OrgReg and add the complete tree to Greg.
Assumes that the header used for authentication is of the type
'X-Gravitee-Api-Key': 'token'.
If the path to the endpoint of the OUs is oregreg/v3/ou/ you want to give
orgreg/v3/ as the url argument (note the trailing slash).
"""
import datetime
import logging
from typing import Union, Mapping, Dict
import orgreg_client
from django.conf import settings
from django.core.management.base import BaseCommand
from orgreg_client import OrgUnit
from greg.models import OrganizationalUnit
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = __doc__
processed: Dict[int, OrganizationalUnit] = {}
def _get_or_create_and_set_values(
self, ou, values: Mapping[str, Union[str, int, bool]]
):
"""Upsert ou with latest values and store in processed dict."""
self.processed[ou.ou_id], created = OrganizationalUnit.objects.get_or_create(
orgreg_id=str(ou.ou_id)
)
for k, v in values.items():
setattr(self.processed[ou.ou_id], k, v)
self.processed[ou.ou_id].save()
logger.info(
"%s %s with %s",
"Created" if created else "Updated",
self.processed[ou.ou_id],
values,
)
def _upsert_ou(self, ou: OrgUnit, ous: Mapping[int, OrgUnit]):
"""
Update or create a OU with current values.
There are three cases:
1. OU has no parent -> Create it.
2. OU has parent and parent exists -> Create it.
3. OU has parent but parent has not been created -> Create parent, then child.
Case 3 is solved by calling this method recursively so that the parent and its
parent are created before the child.
"""
# skip if already processed (happens if a previous ou needed this one as a
# parent)
if ou.ou_id in self.processed:
return
values = {"deleted": False}
# add names if present
if ou.name:
if ou.name.nob:
values["name_nb"] = ou.name.nob
if ou.name.eng:
values["name_en"] = ou.name.eng
# Set inactive if ou is no longer valid
is_inactive = ou.valid_to and ou.valid_to < datetime.date.today()
values["active"] = not is_inactive
# Create OUs without parent (this should only happen for the root node)
if not ou.parent:
self._get_or_create_and_set_values(ou, values)
return
# If OU has parent and it is not already created, we create it and point the
# child to it.
if ou.parent not in self.processed:
self._upsert_ou(ous[ou.parent], ous)
values["parent"] = self.processed[ou.parent]
# Finally create the OU we're currently looking at
self._get_or_create_and_set_values(ou, values)
def handle(self, *args, **options):
"""
Handle import of OUs from OrgReg.
- Updates already present OUs with new information
- Creates not present OUs
- Set not present OUs as inactive
"""
# Empty processed in case of class reuse by tests
self.processed = {}
client = orgreg_client.get_client(**settings.ORGREG_CLIENT)
# Fetch already present OUs and those in OrgReg
current_ous = {int(i.orgreg_id): i for i in OrganizationalUnit.objects.all()}
logger.info("Fetch OUs from Orgreg...")
orgreg_ous = {i.ou_id: i for i in client.get_ou()}
# Set deleted if an OU from Greg no longer exists in OrgReg and inactive if
# valid_to is set to a date before today
logger.info("Set deleted tag on removed OUs...")
for ou_id, ou in current_ous.items():
if ou_id not in orgreg_ous:
logger.info("%s marked as deleted", ou)
ou.deleted = True
ou.save()
continue
# Create new OUs recursively to ensure parents exist before children
logger.info("Update OU values...")
for ou_id, ou in orgreg_ous.items():
self._upsert_ou(ou, orgreg_ous)
# Generated by Django 3.2.7 on 2021-09-08 08:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('greg', '0003_consenttype_mandatory'),
]
operations = [
migrations.AddField(
model_name='organizationalunit',
name='active',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='organizationalunit',
name='deleted',
field=models.BooleanField(default=False),
),
]
......@@ -317,6 +317,8 @@ class OrganizationalUnit(BaseModel):
name_nb = models.CharField(max_length=256)
name_en = models.CharField(max_length=256)
parent = models.ForeignKey("self", on_delete=models.PROTECT, null=True)
active = models.BooleanField(default=True)
deleted = models.BooleanField(default=False)
def __repr__(self):
return "{}(id={!r}, orgreg_id={!r}, name_en={!r}, parent={!r})".format(
......
import datetime
import pytest
from django.core.management import call_command
from orgreg_client import OrgUnit, OrgUnitList
from greg.models import OrganizationalUnit
@pytest.fixture
def old_unit():
OrganizationalUnit.objects.create(orgreg_id="4", name_nb="a", name_en="b")
return OrganizationalUnit.objects.get(orgreg_id="4")
@pytest.fixture
def orgreg_response():
orgreg_ous = OrgUnitList(
__root__=[
OrgUnit(
ou_id=1,
valid_from=datetime.date(year=2020, month=2, day=4),
external_keys=[],
name={"nob": "foo"},
),
OrgUnit(
ou_id=3,
valid_from=datetime.date(year=2020, month=2, day=6),
valid_to=datetime.date(year=2020, month=2, day=7),
parent=2,
name={"nob": "bar"},
external_keys=[],
),
OrgUnit(
ou_id=2,
valid_from=datetime.date(year=2020, month=2, day=5),
parent=1,
name={"eng": "baz"},
external_keys=[],
),
]
)
return orgreg_ous
@pytest.mark.django_db
def test_command_ou_init(requests_mock, old_unit, orgreg_response):
requests_mock.get("https://example.com/fake/ou/", text=orgreg_response.json())
assert OrganizationalUnit.objects.all().count() == 1
call_command("import_from_orgreg")
# Ensure all three new units are imported
assert OrganizationalUnit.objects.all().count() == 4
# Ensure tree is built correctly
assert OrganizationalUnit.objects.get(orgreg_id="3").parent.orgreg_id == "2"
assert OrganizationalUnit.objects.get(orgreg_id="3").parent.parent.orgreg_id == "1"
# Ensure unknown org is marked deleted
assert OrganizationalUnit.objects.get(orgreg_id="4").deleted is True
@pytest.mark.django_db
def test_run_twice(requests_mock, orgreg_response):
requests_mock.get("https://example.com/fake/ou/", text=orgreg_response.json())
assert OrganizationalUnit.objects.all().count() == 0
call_command("import_from_orgreg")
assert OrganizationalUnit.objects.all().count() == 3
call_command("import_from_orgreg")
assert OrganizationalUnit.objects.all().count() == 3
......@@ -8,3 +8,8 @@ try:
from .local import *
except ImportError:
pass
ORGREG_CLIENT = {
"endpoints": {"base_url": "https://example.com/fake/"},
"headers": {"X-Gravitee-Api-Key": "bar"},
}
......@@ -37,3 +37,6 @@ ignore_missing_imports = True
[mypy-pika_context_manager.*]
ignore_missing_imports = True
[mypy-orgreg_client.*]
ignore_missing_imports = True
......@@ -98,7 +98,7 @@ python-versions = "*"
name = "charset-normalizer"
version = "2.0.4"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.5.0"
......@@ -335,7 +335,7 @@ text-unidecode = "1.3"
name = "idna"
version = "3.2"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "dev"
category = "main"
optional = false
python-versions = ">=3.5"
......@@ -523,6 +523,25 @@ category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "orgreg-client"
version = "0.2.3"
description = "Client for the OrgReg-"
category = "main"
optional = false
python-versions = "*"
develop = false
[package.dependencies]
pydantic = "*"
requests = "*"
[package.source]
type = "git"
url = "https://git.app.uib.no/it-bott-integrasjoner/orgreg-client.git"
reference = "v0.2.3"
resolved_reference = "bb60dbba6b48dd82a6a585f4568fd3199eced188"
[[package]]
name = "packaging"
version = "21.0"
......@@ -663,6 +682,21 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pydantic"
version = "1.8.2"
description = "Data validation and settings management using python 3.6 type hinting"
category = "main"
optional = false
python-versions = ">=3.6.1"
[package.dependencies]
typing-extensions = ">=3.7.4.3"
[package.extras]
dotenv = ["python-dotenv (>=0.10.4)"]
email = ["email-validator (>=1.0.3)"]
[[package]]
name = "pygments"
version = "2.10.0"
......@@ -828,7 +862,7 @@ python-versions = "*"
name = "requests"
version = "2.26.0"
description = "Python HTTP for Humans."
category = "dev"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
......@@ -842,6 +876,22 @@ urllib3 = ">=1.21.1,<1.27"
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
[[package]]
name = "requests-mock"
version = "1.9.3"
description = "Mock out responses from the requests package"
category = "dev"
optional = false
python-versions = "*"
[package.dependencies]
requests = ">=2.3,<3"
six = "*"
[package.extras]
fixture = ["fixtures"]
test = ["fixtures", "mock", "purl", "pytest", "sphinx", "testrepository (>=0.0.18)", "testtools"]
[[package]]
name = "rope"
version = "0.19.0"
......@@ -953,7 +1003,7 @@ python-versions = "*"
name = "typing-extensions"
version = "3.10.0.2"
description = "Backported and Experimental Type Hints for Python 3.5+"
category = "dev"
category = "main"
optional = false
python-versions = "*"
......@@ -1008,7 +1058,7 @@ python-versions = "*"
[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "77e4055c61d7e5f8177787a95c79647067fba3bcb298c636a7fb3c3961227b9d"
content-hash = "75c30a6f1bcd72a8d9725dbe92509be0fab8bf9e498ceaaf0a730f2337f439b0"
[metadata.files]
appnope = [
......@@ -1075,6 +1125,9 @@ coverage = [
{file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"},
{file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"},
{file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"},
{file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"},
{file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"},
{file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"},
{file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"},
{file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"},
{file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"},
......@@ -1307,6 +1360,7 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
orgreg-client = []
packaging = [
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
......@@ -1383,6 +1437,30 @@ py = [
{file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
]
pydantic = [
{file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"},
{file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"},
{file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"},
{file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"},
{file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"},
{file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"},
{file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"},
{file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"},
{file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"},
{file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"},
{file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"},
{file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"},
{file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"},
{file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"},
{file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"},
{file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"},
{file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"},
{file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"},
{file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"},
{file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"},
{file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"},
{file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"},
]
pygments = [
{file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"},
{file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"},
......@@ -1457,18 +1535,26 @@ pyyaml = [
{file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
{file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"},
{file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
{file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
{file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"},
{file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
{file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
{file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"},
{file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
{file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
{file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"},
{file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
{file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
......@@ -1520,6 +1606,10 @@ requests = [
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
]
requests-mock = [
{file = "requests-mock-1.9.3.tar.gz", hash = "sha256:8d72abe54546c1fc9696fa1516672f1031d72a55a1d66c85184f972a24ba0eba"},
{file = "requests_mock-1.9.3-py2.py3-none-any.whl", hash = "sha256:0a2d38a117c08bb78939ec163522976ad59a6b7fdd82b709e23bb98004a44970"},
]
rope = [
{file = "rope-0.19.0.tar.gz", hash = "sha256:64e6d747532e1f5c8009ec5aae3e5523a5bcedf516f39a750d57d8ed749d90da"},
]
......
......@@ -15,6 +15,7 @@ djangorestframework = "*"
drf-spectacular = "*"
pika-context-manager = {git = "https://git.app.uib.no/it-bott-integrasjoner/pika-context-manager.git", rev = "v1.2.0"}
psycopg2-binary = "*"
orgreg-client = {git = "https://git.app.uib.no/it-bott-integrasjoner/orgreg-client.git", rev = "v0.2.3" }
python = "^3.9"
python-daemon = "*"
python-json-logger = "*"
......@@ -34,6 +35,7 @@ pylint-django = "*"
pytest-django = "*"
rope = "*"
coverage = "*"
requests-mock = "^1.9.3"
[tool.black]
extend-exclude = '^/greg/migrations/.*\.py'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment