This commit is contained in:
Avram Lubkin 2023-03-03 18:53:11 -05:00 коммит произвёл Avram Lubkin
Родитель 62f63b8e5c
Коммит a4913a6ed8
26 изменённых файлов: 362 добавлений и 944 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -121,3 +121,6 @@ comma.db
# Spreadsheets
*.xlsx
# Local notes
notes

234
CommA.py
Просмотреть файл

@ -1,234 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import argparse
import logging
import Util.Config
from DatabaseDriver.DatabaseDriver import DatabaseDriver
from DatabaseDriver.SqlClasses import Distros, MonitoringSubjects
from DownstreamTracker.MonitorDownstream import monitor_downstream
from UpstreamTracker.MonitorUpstream import monitor_upstream
from Util.Spreadsheet import export_commits, import_commits, update_commits
from Util.Symbols import print_missing_symbols
from Util.Tracking import print_tracked_paths
# TODO: We have a lot of parsers and could refactor them into their
# own modules.
parser = argparse.ArgumentParser(description="Linux Commit Analyzer.")
parser.add_argument(
"-n",
"--dry-run",
action="store_true",
help="Do not connect to production database.",
)
parser.add_argument(
"-v", "--verbose", action="count", default=0, help="increase output verbosity",
)
parser.add_argument(
"--no-fetch",
action="store_true",
help="Do not fetch Git repos (used by developers).",
)
parser.add_argument(
"-s",
"--since",
action="store",
default=Util.Config.since,
help=f"Parameter to pass to underlying Git commands, default is '{Util.Config.since}'.",
)
subparsers = parser.add_subparsers(title="subcommands")
def run(args):
if args.dry_run:
with DatabaseDriver.get_session() as s:
if s.query(Distros).first() is None:
s.add_all(Util.Config.default_distros)
if s.query(MonitoringSubjects).first() is None:
s.add_all(Util.Config.default_monitoring_subjects)
if args.section:
Util.Config.sections = args.section
if args.print_tracked_paths:
print_tracked_paths()
if args.upstream:
monitor_upstream()
if args.downstream:
monitor_downstream()
run_parser = subparsers.add_parser("run", help="Analyze commits in Linux repos.")
run_parser.add_argument(
"-u", "--upstream", action="store_true", help="Monitor the upstream patches."
)
run_parser.add_argument(
"-d", "--downstream", action="store_true", help="Monitor the downstream patches."
)
run_parser.add_argument(
"-p",
"--print-tracked-paths",
action="store_true",
help="Print the paths that would be analyzed.",
)
run_parser.add_argument(
"-s",
"--section",
action="append",
default=Util.Config.sections,
help="List of kernel section entries in MAINTAINERS file to analyze.",
)
run_parser.set_defaults(func=run)
symbol_parser = subparsers.add_parser(
"print-symbols", help="Compare symbols against patches."
)
symbol_parser.add_argument(
"-f",
"--file",
type=argparse.FileType("r"),
default="symbols.txt",
help="File with symbols to compare against.",
)
symbol_parser.set_defaults(func=(lambda args: print_missing_symbols(args.file)))
def spreadsheet(args):
if args.import_commits:
import_commits(args.in_file)
if args.export_commits:
export_commits(args.in_file, args.out_file)
if args.update_commits:
update_commits(args.in_file, args.out_file)
spreadsheet_parser = subparsers.add_parser(
"spreadsheet", help="Export to Excel Spreadsheet.",
)
spreadsheet_parser.add_argument(
"-i",
"--import-commits",
action="store_true",
help="Import commits from spreadsheet into database.",
)
spreadsheet_parser.add_argument(
"-e",
"--export-commits",
action="store_true",
help="Export commits from database into spreadsheet.",
)
spreadsheet_parser.add_argument(
"-u",
"--update-commits",
action="store_true",
help="Export downstream distro statuses from database into spreadsheet.",
)
spreadsheet_parser.add_argument(
"-f", "--in-file", default="input.xlsx", help="Spreadsheet to read in.",
)
spreadsheet_parser.add_argument(
"-o", "--out-file", default="output.xlsx", help="Spreadsheet to write out.",
)
spreadsheet_parser.set_defaults(func=spreadsheet)
def get_distros(args):
with DatabaseDriver.get_session() as s:
print("DistroID\tRevision")
for distro, revision in (
s.query(Distros.distroID, MonitoringSubjects.revision)
.outerjoin(
MonitoringSubjects, Distros.distroID == MonitoringSubjects.distroID
)
.all()
):
print(f"{distro}\t{revision}")
logging.debug("Successfully printed revisions")
print_distro_parser = subparsers.add_parser(
"print-distros", help="Print current <distro-name, revision> info.",
)
print_distro_parser.set_defaults(func=get_distros)
def add_distro(args):
with DatabaseDriver.get_session() as s:
s.add(Distros(distroID=args.name, repoLink=args.url))
s.add(MonitoringSubjects(distroID=args.name, revision=args.revision))
logging.info(f"Successfully added new distro: {args.name}")
distro_parser = subparsers.add_parser(
"add-distro", help="Add a distro to the database."
)
distro_parser.add_argument(
"-n",
"--name",
required=True,
help="Database name (ID) for distro, e.g. 'Ubuntu18.04'.",
)
distro_parser.add_argument(
"-u",
"--url",
required=True,
help="Git repository URL for distro, e.g. 'https://git.launchpad.net/...'.",
)
distro_parser.add_argument(
"-r",
"--revision",
required=True,
help="Repository revision to track. For adding a new branch use distro-name/branch-name format. e.g. 'SUSE12/SUSE12-SP5-AZURE'.",
)
distro_parser.set_defaults(func=add_distro)
def add_kernel(args):
with DatabaseDriver.get_session() as s:
s.add(MonitoringSubjects(distroID=args.name, revision=args.revision))
logging.info(
f"Successfully added new revision '{args.revision}' for distro '{args.name}'"
)
kernel_parser = subparsers.add_parser(
"add-kernel", help="Add new kernel/revision to track for pre-existing distros."
)
kernel_parser.add_argument(
"-n",
"--name",
required=True,
help="Database name (ID) for distro, e.g. 'Ubuntu18.04'",
)
kernel_parser.add_argument(
"-r",
"--revision",
required=True,
help="Repository revision to track. For adding a new branch use distro-name/branch-name format. e.g. SUSE12/SUSE12-SP5-AZURE",
)
kernel_parser.set_defaults(func=add_kernel)
logging.basicConfig(
level=logging.WARNING,
format="%(asctime)s %(name)-5s %(levelname)-7s %(message)s",
datefmt="%m-%d %H:%M",
)
if __name__ == "__main__":
args = parser.parse_args()
Util.Config.verbose = args.verbose
logging_level = (
logging.WARNING
if Util.Config.verbose == 0
else logging.INFO
if Util.Config.verbose == 1
else logging.DEBUG
)
logging.getLogger().setLevel(logging_level)
Util.Config.dry_run = args.dry_run
Util.Config.since = args.since
Util.Config.fetch = not args.no_fetch
print("Welcome to Commit Analyzer!")
args.func(args)
print("Commit Analyzer completed!")

6
MANIFEST.in Normal file
Просмотреть файл

@ -0,0 +1,6 @@
# This file provides fine-grain control over what files are included in a
# Python source distribution (sdist).
# For more details see https://packaging.python.org/en/latest/guides/using-manifest-in/
exclude .*
exclude azure-pipelines.yml

Просмотреть файл

Просмотреть файл

@ -6,9 +6,9 @@ from contextlib import contextmanager
import sqlalchemy
import Util.Config
from DatabaseDriver.Credentials import DatabaseCredentials
from DatabaseDriver.SqlClasses import Base
from comma.DatabaseDriver.Credentials import DatabaseCredentials
from comma.DatabaseDriver.SqlClasses import Base
from comma.Util import Config
# TODO: Rename this class because it conflicts with the module name.
@ -24,11 +24,11 @@ class DatabaseDriver:
"""
Initialize Database connection
"""
if Util.Config.dry_run:
if Config.dry_run:
db_file = "comma.db"
logging.info(f"Using local SQLite database at '{db_file}'.")
engine = sqlalchemy.create_engine(
f"sqlite:///{db_file}", echo=(Util.Config.verbose > 2)
f"sqlite:///{db_file}", echo=(Config.verbose > 2)
)
else:
logging.info("Connecting to remote database...")
@ -38,7 +38,7 @@ class DatabaseDriver:
)
engine = sqlalchemy.create_engine(
f"mssql+pyodbc:///?odbc_connect={params}",
echo=(Util.Config.verbose > 2),
echo=(Config.verbose > 2),
)
logging.info("Connected!")
Base.metadata.bind = engine

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -10,10 +10,10 @@ from datetime import datetime
import git
import Util.Constants as cst
from DatabaseDriver.DistroMatch import DistroMatch
from UpstreamTracker.MonitorUpstream import parse_maintainers, sanitize_filenames
from UpstreamTracker.ParseData import get_patch_object, insert_patch
import comma.Util.Constants as cst
from comma.DatabaseDriver.DistroMatch import DistroMatch
from comma.UpstreamTracker.MonitorUpstream import parse_maintainers, sanitize_filenames
from comma.UpstreamTracker.ParseData import get_patch_object, insert_patch
def contains_filepath(filepath1, filepath2):

Просмотреть файл

@ -5,8 +5,8 @@ from typing import List
from fuzzywuzzy import fuzz
from DatabaseDriver.SqlClasses import PatchData
from Objects.PatchDiffs import PatchDiffs
from comma.DatabaseDriver.SqlClasses import PatchData
from comma.Objects.PatchDiffs import PatchDiffs
def patch_matches(downstream_patches: List[PatchData], upstream: PatchData) -> bool:

Просмотреть файл

@ -2,17 +2,17 @@
# Licensed under the MIT License.
import logging
import Util.Config
from DatabaseDriver.DatabaseDriver import DatabaseDriver
from DatabaseDriver.SqlClasses import (
from comma.Util import Config
from comma.DatabaseDriver.DatabaseDriver import DatabaseDriver
from comma.DatabaseDriver.SqlClasses import (
Distros,
MonitoringSubjects,
MonitoringSubjectsMissingPatches,
PatchData,
)
from DownstreamTracker.DownstreamMatcher import patch_matches
from UpstreamTracker.ParseData import process_commits
from Util.Tracking import get_linux_repo, get_tracked_paths
from comma.DownstreamTracker.DownstreamMatcher import patch_matches
from comma.UpstreamTracker.ParseData import process_commits
from comma.Util.Tracking import get_linux_repo, get_tracked_paths
def update_revisions_for_distro(distro_id, revs):
@ -186,10 +186,10 @@ def monitor_downstream():
repo.create_remote(distroID, url=repoLink)
# Update all remotes, and tags of all remotes
if Util.Config.fetch:
if Config.fetch:
logging.info("Fetching updates to all repos and tags...")
repo.git.fetch(
"--all", "--tags", "--force", f"--shallow-since='{Util.Config.since}'"
"--all", "--tags", "--force", f"--shallow-since='{Config.since}'"
)
logging.debug("Fetched!")

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -2,7 +2,7 @@
# Licensed under the MIT License.
import logging
from UpstreamTracker.ParseData import process_commits
from comma.UpstreamTracker.ParseData import process_commits
def monitor_upstream():

Просмотреть файл

@ -4,10 +4,10 @@ import logging
from datetime import datetime
from typing import List, Optional, Set
import Util.Config
from DatabaseDriver.DatabaseDriver import DatabaseDriver
from DatabaseDriver.SqlClasses import PatchData
from Util.Tracking import get_filenames, get_linux_repo, get_tracked_paths
from comma.Util import Config
from comma.DatabaseDriver.DatabaseDriver import DatabaseDriver
from comma.DatabaseDriver.SqlClasses import PatchData
from comma.Util.Tracking import get_filenames, get_linux_repo, get_tracked_paths
def should_keep_line(line: str):
@ -32,7 +32,7 @@ def process_commits(
commit_ids: Optional[Set[str]] = None,
revision: str = "origin/master",
add_to_database: bool = False,
since: str = Util.Config.since,
since: str = Config.since,
) -> List[PatchData]:
"""
Look at all commits in the given repo and handle based on distro.

Просмотреть файл

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
from DatabaseDriver.SqlClasses import Distros, MonitoringSubjects
from comma.DatabaseDriver.SqlClasses import Distros, MonitoringSubjects
dry_run = False
fetch = True

Просмотреть файл

@ -14,11 +14,11 @@ from openpyxl.cell import cell
from openpyxl.workbook import workbook
from openpyxl.worksheet import worksheet
import Util.Config
import Util.Tracking
from DatabaseDriver.DatabaseDriver import DatabaseDriver
from DatabaseDriver.SqlClasses import Distros, MonitoringSubjects, PatchData
from UpstreamTracker.ParseData import process_commits
import comma.Util.Config
from comma.Util import Tracking
from comma.DatabaseDriver.DatabaseDriver import DatabaseDriver
from comma.DatabaseDriver.SqlClasses import Distros, MonitoringSubjects, PatchData
from comma.UpstreamTracker.ParseData import process_commits
def get_db_commits() -> Dict[str, int]:
@ -114,7 +114,7 @@ def include_commit(sha: str, repo: git.Repo, base_commit: git.Commit) -> bool:
logging.debug(f"Commit '{sha}' is too old!")
return False
# Skip commits to tools.
filenames = Util.Tracking.get_filenames(commit)
filenames = Tracking.get_filenames(commit)
if any(f.startswith("tools/hv/") for f in filenames):
logging.debug(f"Commit '{sha}' is to 'tools/hv/'!")
return False
@ -170,7 +170,7 @@ def export_commits(in_file: str, out_file: str) -> None:
# Collect the commits in the database which are not in the
# workbook, but that we want to include.
db_commits = get_db_commits()
repo = Util.Tracking.get_linux_repo()
repo = Tracking.get_linux_repo()
tag = "v4.15"
logging.info(f"Skipping commits before tag '{tag}'!")
base_commit = repo.commit(tag)

Просмотреть файл

@ -3,9 +3,9 @@
import logging
import subprocess
from DatabaseDriver.DatabaseDriver import DatabaseDriver
from DatabaseDriver.SqlClasses import PatchData
from Util.Tracking import get_repo, get_tracked_paths
from comma.DatabaseDriver.DatabaseDriver import DatabaseDriver
from comma.DatabaseDriver.SqlClasses import PatchData
from comma.Util.Tracking import get_repo, get_tracked_paths
def list_diff(list1, list2):

Просмотреть файл

@ -8,7 +8,7 @@ from typing import List, Set
import git
import Util.Config
from comma.Util import Config
def get_filenames(commit: git.Commit) -> List[str]:
@ -51,20 +51,20 @@ def get_repo(
logging.info(f"Pulling '{name}' repo...")
repo.remotes.origin.pull()
logging.info("Pulled!")
elif Util.Config.fetch:
elif Config.fetch:
logging.info(f"Fetching '{name}' repo...")
repo.git.fetch(
"--all",
"--tags",
"--force",
f"--shallow-since={Util.Config.since}",
f"--shallow-since={Config.since}",
)
logging.info("Fetched!")
else:
logging.info(f"Cloning '{name}' repo from '{url}'...")
args = {}
if shallow:
args.update({"shallow_since": Util.Config.since})
args.update({"shallow_since": Config.since})
repo = git.Repo.clone_from(url, path, **args)
logging.info("Cloned!")
# We either cloned, pulled, fetched, or purposefully skipped doing
@ -113,7 +113,7 @@ def get_files(section: str, content: List[str]) -> Set[str]:
TRACKED_PATHS: List[str] = None
def get_tracked_paths(sections=Util.Config.sections) -> List[str]:
def get_tracked_paths(sections=Config.sections) -> List[str]:
"""Get list of files from MAINTAINERS for given sections."""
global TRACKED_PATHS
if TRACKED_PATHS is not None:

Просмотреть файл

Просмотреть файл

@ -1,2 +1,4 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
__version__ = "0.2.0"

255
comma/__main__.py Executable file
Просмотреть файл

@ -0,0 +1,255 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import argparse
import logging
from typing import Optional
from comma.DatabaseDriver.DatabaseDriver import DatabaseDriver
from comma.DatabaseDriver.SqlClasses import Distros, MonitoringSubjects
from comma.DownstreamTracker.MonitorDownstream import monitor_downstream
from comma.UpstreamTracker.MonitorUpstream import monitor_upstream
from comma.Util import Config
from comma.Util.Spreadsheet import export_commits, import_commits, update_commits
from comma.Util.Symbols import print_missing_symbols
from comma.Util.Tracking import print_tracked_paths
def run(args):
if args.dry_run:
with DatabaseDriver.get_session() as s:
if s.query(Distros).first() is None:
s.add_all(Config.default_distros)
if s.query(MonitoringSubjects).first() is None:
s.add_all(Config.default_monitoring_subjects)
if args.section:
Config.sections = args.section
if args.print_tracked_paths:
print_tracked_paths()
if args.upstream:
monitor_upstream()
if args.downstream:
monitor_downstream()
def spreadsheet(args):
if args.import_commits:
import_commits(args.in_file)
if args.export_commits:
export_commits(args.in_file, args.out_file)
if args.update_commits:
update_commits(args.in_file, args.out_file)
def get_distros(args):
with DatabaseDriver.get_session() as s:
print("DistroID\tRevision")
for distro, revision in (
s.query(Distros.distroID, MonitoringSubjects.revision)
.outerjoin(
MonitoringSubjects, Distros.distroID == MonitoringSubjects.distroID
)
.all()
):
print(f"{distro}\t{revision}")
logging.debug("Successfully printed revisions")
def add_distro(args):
with DatabaseDriver.get_session() as s:
s.add(Distros(distroID=args.name, repoLink=args.url))
s.add(MonitoringSubjects(distroID=args.name, revision=args.revision))
logging.info(f"Successfully added new distro: {args.name}")
def add_kernel(args):
with DatabaseDriver.get_session() as s:
s.add(MonitoringSubjects(distroID=args.name, revision=args.revision))
logging.info(
f"Successfully added new revision '{args.revision}' for distro '{args.name}'"
)
def get_cli_options(args: Optional[str] = None) -> argparse.Namespace:
"""
Parse CLI options and return a namespace
"""
# TODO: We have a lot of parsers and could refactor them into their
# own modules.
parser = argparse.ArgumentParser(description="Linux Commit Analyzer.")
parser.add_argument(
"-n",
"--dry-run",
action="store_true",
help="Do not connect to production database.",
)
parser.add_argument(
"-v",
"--verbose",
action="count",
default=0,
help="increase output verbosity",
)
parser.add_argument(
"--no-fetch",
action="store_true",
help="Do not fetch Git repos (used by developers).",
)
parser.add_argument(
"-s",
"--since",
action="store",
default=Config.since,
help=f"Parameter to pass to underlying Git commands, default is '{Config.since}'.",
)
subparsers = parser.add_subparsers(title="subcommands")
run_parser = subparsers.add_parser("run", help="Analyze commits in Linux repos.")
run_parser.add_argument(
"-u", "--upstream", action="store_true", help="Monitor the upstream patches."
)
run_parser.add_argument(
"-d",
"--downstream",
action="store_true",
help="Monitor the downstream patches.",
)
run_parser.add_argument(
"-p",
"--print-tracked-paths",
action="store_true",
help="Print the paths that would be analyzed.",
)
run_parser.add_argument(
"-s",
"--section",
action="append",
default=Config.sections,
help="List of kernel section entries in MAINTAINERS file to analyze.",
)
run_parser.set_defaults(func=run)
symbol_parser = subparsers.add_parser(
"print-symbols", help="Compare symbols against patches."
)
symbol_parser.add_argument(
"-f",
"--file",
type=argparse.FileType("r"),
default="symbols.txt",
help="File with symbols to compare against.",
)
symbol_parser.set_defaults(func=(lambda args: print_missing_symbols(args.file)))
spreadsheet_parser = subparsers.add_parser(
"spreadsheet",
help="Export to Excel Spreadsheet.",
)
spreadsheet_parser.add_argument(
"-i",
"--import-commits",
action="store_true",
help="Import commits from spreadsheet into database.",
)
spreadsheet_parser.add_argument(
"-e",
"--export-commits",
action="store_true",
help="Export commits from database into spreadsheet.",
)
spreadsheet_parser.add_argument(
"-u",
"--update-commits",
action="store_true",
help="Export downstream distro statuses from database into spreadsheet.",
)
spreadsheet_parser.add_argument(
"-f",
"--in-file",
default="input.xlsx",
help="Spreadsheet to read in.",
)
spreadsheet_parser.add_argument(
"-o",
"--out-file",
default="output.xlsx",
help="Spreadsheet to write out.",
)
spreadsheet_parser.set_defaults(func=spreadsheet)
print_distro_parser = subparsers.add_parser(
"print-distros",
help="Print current <distro-name, revision> info.",
)
print_distro_parser.set_defaults(func=get_distros)
distro_parser = subparsers.add_parser(
"add-distro", help="Add a distro to the database."
)
distro_parser.add_argument(
"-n",
"--name",
required=True,
help="Database name (ID) for distro, e.g. 'Ubuntu18.04'.",
)
distro_parser.add_argument(
"-u",
"--url",
required=True,
help="Git repository URL for distro, e.g. 'https://git.launchpad.net/...'.",
)
distro_parser.add_argument(
"-r",
"--revision",
required=True,
help="Repository revision to track. For adding a new branch use distro-name/branch-name format. e.g. 'SUSE12/SUSE12-SP5-AZURE'.",
)
distro_parser.set_defaults(func=add_distro)
kernel_parser = subparsers.add_parser(
"add-kernel", help="Add new kernel/revision to track for pre-existing distros."
)
kernel_parser.add_argument(
"-n",
"--name",
required=True,
help="Database name (ID) for distro, e.g. 'Ubuntu18.04'",
)
kernel_parser.add_argument(
"-r",
"--revision",
required=True,
help="Repository revision to track. For adding a new branch use distro-name/branch-name format. e.g. SUSE12/SUSE12-SP5-AZURE",
)
kernel_parser.set_defaults(func=add_kernel)
return parser.parse_args(args=args)
def main(args: Optional[str] = None) -> None:
"""
Main entrypoint for CLI
"""
args = get_cli_options(args)
logging.basicConfig(
level={0: logging.WARNING, 1: logging.INFO}.get(args.verbose, logging.DEBUG),
format="%(asctime)s %(name)-5s %(levelname)-7s %(message)s",
datefmt="%m-%d %H:%M",
)
Config.verbose = args.verbose
Config.dry_run = args.dry_run
Config.since = args.since
Config.fetch = not args.no_fetch
print("Welcome to Commit Analyzer!")
args.func(args)
print("Commit Analyzer completed!")
if __name__ == "__main__":
main()

642
poetry.lock сгенерированный
Просмотреть файл

@ -1,642 +0,0 @@
[[package]]
category = "dev"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
name = "appdirs"
optional = false
python-versions = "*"
version = "1.4.4"
[[package]]
category = "dev"
description = "Classes Without Boilerplate"
name = "attrs"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.3.0"
[package.extras]
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
[[package]]
category = "dev"
description = "The uncompromising code formatter."
name = "black"
optional = false
python-versions = ">=3.6"
version = "19.10b0"
[package.dependencies]
appdirs = "*"
attrs = ">=18.1.0"
click = ">=6.5"
pathspec = ">=0.6,<1"
regex = "*"
toml = ">=0.9.4"
typed-ast = ">=1.4.0"
[package.extras]
d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
[[package]]
category = "dev"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "7.1.2"
[[package]]
category = "main"
description = "An implementation of lxml.xmlfile for the standard library"
name = "et-xmlfile"
optional = false
python-versions = "*"
version = "1.0.1"
[[package]]
category = "dev"
description = "the modular source code checker: pep8 pyflakes and co"
name = "flake8"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
version = "3.8.3"
[package.dependencies]
mccabe = ">=0.6.0,<0.7.0"
pycodestyle = ">=2.6.0a1,<2.7.0"
pyflakes = ">=2.2.0,<2.3.0"
[package.dependencies.importlib-metadata]
python = "<3.8"
version = "*"
[[package]]
category = "dev"
description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle."
name = "flake8-bugbear"
optional = false
python-versions = ">=3.6"
version = "20.1.4"
[package.dependencies]
attrs = ">=19.2.0"
flake8 = ">=3.0.0"
[[package]]
category = "main"
description = "Fuzzy string matching in python"
name = "fuzzywuzzy"
optional = false
python-versions = "*"
version = "0.18.0"
[package.extras]
speedup = ["python-levenshtein (>=0.12)"]
[[package]]
category = "main"
description = "Git Object Database"
name = "gitdb"
optional = false
python-versions = ">=3.4"
version = "4.0.5"
[package.dependencies]
smmap = ">=3.0.1,<4"
[[package]]
category = "main"
description = "Python Git Library"
name = "gitpython"
optional = false
python-versions = ">=3.4"
version = "3.1.7"
[package.dependencies]
gitdb = ">=4.0.1,<5"
[[package]]
category = "dev"
description = "Read metadata from Python packages"
marker = "python_version < \"3.8\""
name = "importlib-metadata"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
version = "1.7.0"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["sphinx", "rst.linker"]
testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
[[package]]
category = "dev"
description = "A Python utility / library to sort Python imports."
name = "isort"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "4.3.21"
[package.extras]
pipfile = ["pipreqs", "requirementslib"]
pyproject = ["toml"]
requirements = ["pipreqs", "pip-api"]
xdg_home = ["appdirs (>=1.4.0)"]
[[package]]
category = "main"
description = "Julian dates from proleptic Gregorian and Julian calendars."
name = "jdcal"
optional = false
python-versions = "*"
version = "1.4.1"
[[package]]
category = "dev"
description = "An autocompletion tool for Python that can be used for text editors."
name = "jedi"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.17.2"
[package.dependencies]
parso = ">=0.7.0,<0.8.0"
[package.extras]
qa = ["flake8 (3.7.9)"]
testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"]
[[package]]
category = "dev"
description = "McCabe checker, plugin for flake8"
name = "mccabe"
optional = false
python-versions = "*"
version = "0.6.1"
[[package]]
category = "main"
description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
name = "openpyxl"
optional = false
python-versions = ">=3.6,"
version = "3.0.4"
[package.dependencies]
et-xmlfile = "*"
jdcal = "*"
[[package]]
category = "dev"
description = "A Python Parser"
name = "parso"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.7.1"
[package.extras]
testing = ["docopt", "pytest (>=3.0.7)"]
[[package]]
category = "dev"
description = "Utility library for gitignore style pattern matching of file paths."
name = "pathspec"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.8.0"
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
name = "pluggy"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.13.1"
[package.dependencies]
[package.dependencies.importlib-metadata]
python = "<3.8"
version = ">=0.12"
[package.extras]
dev = ["pre-commit", "tox"]
[[package]]
category = "dev"
description = "Python style guide checker"
name = "pycodestyle"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.6.0"
[[package]]
category = "dev"
description = "passive checker of Python programs"
name = "pyflakes"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.2.0"
[[package]]
category = "dev"
description = "Black plugin for the Python Language Server"
name = "pyls-black"
optional = false
python-versions = ">=3.6"
version = "0.4.6"
[package.dependencies]
black = ">=19.3b0"
python-language-server = "*"
toml = "*"
[package.extras]
dev = ["isort (>=5.0)", "flake8", "pytest", "mypy"]
[[package]]
category = "dev"
description = "Isort plugin for python-language-server"
name = "pyls-isort"
optional = false
python-versions = "*"
version = "0.1.1"
[package.dependencies]
isort = "*"
python-language-server = "*"
[[package]]
category = "main"
description = "DB API Module for ODBC"
name = "pyodbc"
optional = false
python-versions = "*"
version = "4.0.30"
[[package]]
category = "dev"
description = "JSON RPC 2.0 server library"
name = "python-jsonrpc-server"
optional = false
python-versions = "*"
version = "0.3.4"
[package.dependencies]
ujson = "<=1.35"
[package.extras]
test = ["versioneer", "pylint", "pycodestyle", "pyflakes", "pytest", "mock", "pytest-cov", "coverage"]
[[package]]
category = "dev"
description = "Python Language Server for the Language Server Protocol"
name = "python-language-server"
optional = false
python-versions = "*"
version = "0.34.1"
[package.dependencies]
jedi = ">=0.17.0,<0.18.0"
pluggy = "*"
python-jsonrpc-server = ">=0.3.2"
ujson = "<=1.35"
[package.dependencies.flake8]
optional = true
version = ">=3.8.0"
[package.dependencies.rope]
optional = true
version = ">0.10.5"
[package.extras]
all = ["autopep8", "flake8 (>=3.8.0)", "mccabe (>=0.6.0,<0.7.0)", "pycodestyle (>=2.6.0,<2.7.0)", "pydocstyle (>=2.0.0)", "pyflakes (>=2.2.0,<2.3.0)", "pylint", "rope (>=0.10.5)", "yapf"]
autopep8 = ["autopep8"]
flake8 = ["flake8 (>=3.8.0)"]
mccabe = ["mccabe (>=0.6.0,<0.7.0)"]
pycodestyle = ["pycodestyle (>=2.6.0,<2.7.0)"]
pydocstyle = ["pydocstyle (>=2.0.0)"]
pyflakes = ["pyflakes (>=2.2.0,<2.3.0)"]
pylint = ["pylint"]
rope = ["rope (>0.10.5)"]
test = ["versioneer", "pylint", "pytest", "mock", "pytest-cov", "coverage", "numpy", "pandas", "matplotlib", "pyqt5"]
yapf = ["yapf"]
[[package]]
category = "main"
description = "Python extension for computing string edit distances and similarities."
name = "python-levenshtein"
optional = false
python-versions = "*"
version = "0.12.0"
[package.dependencies]
setuptools = "*"
[[package]]
category = "dev"
description = "Alternative regular expression module, to replace re."
name = "regex"
optional = false
python-versions = "*"
version = "2020.7.14"
[[package]]
category = "dev"
description = "a python refactoring library..."
name = "rope"
optional = false
python-versions = "*"
version = "0.17.0"
[package.extras]
dev = ["pytest"]
[[package]]
category = "main"
description = "A pure Python implementation of a sliding window memory map manager"
name = "smmap"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "3.0.4"
[[package]]
category = "main"
description = "Database Abstraction Library"
name = "sqlalchemy"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.3.18"
[package.extras]
mssql = ["pyodbc"]
mssql_pymssql = ["pymssql"]
mssql_pyodbc = ["pyodbc"]
mysql = ["mysqlclient"]
oracle = ["cx-oracle"]
postgresql = ["psycopg2"]
postgresql_pg8000 = ["pg8000"]
postgresql_psycopg2binary = ["psycopg2-binary"]
postgresql_psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql"]
[[package]]
category = "dev"
description = "Python Library for Tom's Obvious, Minimal Language"
name = "toml"
optional = false
python-versions = "*"
version = "0.10.1"
[[package]]
category = "dev"
description = "a fork of Python 2 and 3 ast modules with type comment support"
name = "typed-ast"
optional = false
python-versions = "*"
version = "1.4.1"
[[package]]
category = "dev"
description = "Ultra fast JSON encoder and decoder for Python"
marker = "platform_system != \"Windows\""
name = "ujson"
optional = false
python-versions = "*"
version = "1.35"
[[package]]
category = "dev"
description = "Backport of pathlib-compatible object wrapper for zip files"
marker = "python_version < \"3.8\""
name = "zipp"
optional = false
python-versions = ">=3.6"
version = "3.1.0"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
content-hash = "ce1102c3c103f714fe6a1845069e989952a67a89f0e6950da0ef818aae321909"
lock-version = "1.0"
python-versions = "^3.6"
[metadata.files]
appdirs = [
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
attrs = [
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
]
black = [
{file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"},
{file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"},
]
click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
]
et-xmlfile = [
{file = "et_xmlfile-1.0.1.tar.gz", hash = "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b"},
]
flake8 = [
{file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"},
{file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"},
]
flake8-bugbear = [
{file = "flake8-bugbear-20.1.4.tar.gz", hash = "sha256:bd02e4b009fb153fe6072c31c52aeab5b133d508095befb2ffcf3b41c4823162"},
{file = "flake8_bugbear-20.1.4-py36.py37.py38-none-any.whl", hash = "sha256:a3ddc03ec28ba2296fc6f89444d1c946a6b76460f859795b35b77d4920a51b63"},
]
fuzzywuzzy = [
{file = "fuzzywuzzy-0.18.0-py2.py3-none-any.whl", hash = "sha256:928244b28db720d1e0ee7587acf660ea49d7e4c632569cad4f1cd7e68a5f0993"},
{file = "fuzzywuzzy-0.18.0.tar.gz", hash = "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8"},
]
gitdb = [
{file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"},
{file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"},
]
gitpython = [
{file = "GitPython-3.1.7-py3-none-any.whl", hash = "sha256:fa3b92da728a457dd75d62bb5f3eb2816d99a7fe6c67398e260637a40e3fafb5"},
{file = "GitPython-3.1.7.tar.gz", hash = "sha256:2db287d71a284e22e5c2846042d0602465c7434d910406990d5b74df4afb0858"},
]
importlib-metadata = [
{file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
{file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
]
isort = [
{file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
{file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
]
jdcal = [
{file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"},
{file = "jdcal-1.4.1.tar.gz", hash = "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8"},
]
jedi = [
{file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"},
{file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"},
]
mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
]
openpyxl = [
{file = "openpyxl-3.0.4-py2.py3-none-any.whl", hash = "sha256:6e62f058d19b09b95d20ebfbfb04857ad08d0833190516c1660675f699c6186f"},
{file = "openpyxl-3.0.4.tar.gz", hash = "sha256:d88dd1480668019684c66cfff3e52a5de4ed41e9df5dd52e008cbf27af0dbf87"},
]
parso = [
{file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"},
{file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"},
]
pathspec = [
{file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"},
{file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
]
pycodestyle = [
{file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"},
{file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"},
]
pyflakes = [
{file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"},
{file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"},
]
pyls-black = [
{file = "pyls-black-0.4.6.tar.gz", hash = "sha256:33700e5ed605636ea7ba39188a1362d2f8602f7301f8f2b8544773886f965663"},
{file = "pyls_black-0.4.6-py3-none-any.whl", hash = "sha256:8f5fb8fed503588c10435d2d48e2c3751437f1bdb8116134b05a4591c4899940"},
]
pyls-isort = [
{file = "pyls-isort-0.1.1.tar.gz", hash = "sha256:5bad833dab833c4e8d61172428c6ff16e4d334d986fe5dd809aa55c2e7e4fb7f"},
{file = "pyls_isort-0.1.1-py3-none-any.whl", hash = "sha256:eaf323e12d652ed4ccf8365c1f65d55923e5ee5a9cbfa27bdd5f2941a14d16e6"},
]
pyodbc = [
{file = "pyodbc-4.0.30-cp27-cp27m-win32.whl", hash = "sha256:a1af49a2f4f0abbafdc018d510e31561d3f9472725dc1d49cce3bd2e10e9ec18"},
{file = "pyodbc-4.0.30-cp27-cp27m-win_amd64.whl", hash = "sha256:eb9e7a4a5126f2695f307b2a6b0b94cbfccfe7481be2c0d33f5456515328f1cc"},
{file = "pyodbc-4.0.30-cp27-none-macosx_10_15_x86_64.whl", hash = "sha256:3a8212be2e49ff29d71d40a9c1af2cdaa71dcc7246cf80a0f9c7254de47ea4a9"},
{file = "pyodbc-4.0.30-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2f0079951016729b51babebd6aa8112ecef53e11eea3116036c4ec7105f41514"},
{file = "pyodbc-4.0.30-cp36-cp36m-win32.whl", hash = "sha256:7113daddcf346ff095904c568d1e1019f567da74058b4e69099e23bc98211691"},
{file = "pyodbc-4.0.30-cp36-cp36m-win_amd64.whl", hash = "sha256:d9d1469786519c3b545168b45db7c3ece3b493c89d51bb5732d38a2eac6d0863"},
{file = "pyodbc-4.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:52a42be6561932d74bbcc5b0f54dcdcf2eceae3b03192fc0db64a5020bbca057"},
{file = "pyodbc-4.0.30-cp37-cp37m-win32.whl", hash = "sha256:8fa4147bf3bff1b66a9b1a0063094ca1686b9319383e711e7c193c2b4728b572"},
{file = "pyodbc-4.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:1b8ed92bd50c6d83dec88153880405434bc261bb013ca02809827bb3ffbb319a"},
{file = "pyodbc-4.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d4ffeab51dcc03c4c1a9a200f70999ce9b827c91defc4f5740633a6d47d3a206"},
{file = "pyodbc-4.0.30-cp38-cp38-win32.whl", hash = "sha256:d3ad340e0053b6ec4130957efbcecce6de48d68e7e78792ea7588e27ffa629f1"},
{file = "pyodbc-4.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:bce7e41c7cfc06ec976245f361221dfdd0f04e804010cf255cbb36985f6c3406"},
{file = "pyodbc-4.0.30.tar.gz", hash = "sha256:852b5deeeb3366af8b4408efed993501708be45d221881bce60c9aac54be726a"},
]
python-jsonrpc-server = [
{file = "python-jsonrpc-server-0.3.4.tar.gz", hash = "sha256:c73bf5495c9dd4d2f902755bedeb6da5afe778e0beee82f0e195c4655352fe37"},
{file = "python_jsonrpc_server-0.3.4-py3-none-any.whl", hash = "sha256:1f85f75f37f923149cc0aa078474b6df55b708e82ed819ca8846a65d7d0ada7f"},
]
python-language-server = [
{file = "python-language-server-0.34.1.tar.gz", hash = "sha256:b96ff466b5aa24e212493de863899298f229a9e250e7353972563c7f2495d23d"},
{file = "python_language_server-0.34.1-py3-none-any.whl", hash = "sha256:47dd678c261f8fc8af16ce738a637e49e0597ad5e4af10b76f4144ab2d96f247"},
]
python-levenshtein = [
{file = "python-Levenshtein-0.12.0.tar.gz", hash = "sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1"},
]
regex = [
{file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"},
{file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"},
{file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"},
{file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"},
{file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"},
{file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"},
{file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"},
{file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"},
{file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"},
{file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"},
{file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"},
{file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"},
{file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"},
{file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"},
{file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"},
{file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"},
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"},
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"},
{file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"},
{file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"},
{file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"},
]
rope = [
{file = "rope-0.17.0.tar.gz", hash = "sha256:658ad6705f43dcf3d6df379da9486529cf30e02d9ea14c5682aa80eb33b649e1"},
]
smmap = [
{file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"},
{file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"},
]
sqlalchemy = [
{file = "SQLAlchemy-1.3.18-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:f11c2437fb5f812d020932119ba02d9e2bc29a6eca01a055233a8b449e3e1e7d"},
{file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0ec575db1b54909750332c2e335c2bb11257883914a03bc5a3306a4488ecc772"},
{file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f57be5673e12763dd400fea568608700a63ce1c6bd5bdbc3cc3a2c5fdb045274"},
{file = "SQLAlchemy-1.3.18-cp27-cp27m-win32.whl", hash = "sha256:8cac7bb373a5f1423e28de3fd5fc8063b9c8ffe8957dc1b1a59cb90453db6da1"},
{file = "SQLAlchemy-1.3.18-cp27-cp27m-win_amd64.whl", hash = "sha256:adad60eea2c4c2a1875eb6305a0b6e61a83163f8e233586a4d6a55221ef984fe"},
{file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57aa843b783179ab72e863512e14bdcba186641daf69e4e3a5761d705dcc35b1"},
{file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:621f58cd921cd71ba6215c42954ffaa8a918eecd8c535d97befa1a8acad986dd"},
{file = "SQLAlchemy-1.3.18-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fc728ece3d5c772c196fd338a99798e7efac7a04f9cb6416299a3638ee9a94cd"},
{file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:736d41cfebedecc6f159fc4ac0769dc89528a989471dc1d378ba07d29a60ba1c"},
{file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:427273b08efc16a85aa2b39892817e78e3ed074fcb89b2a51c4979bae7e7ba98"},
{file = "SQLAlchemy-1.3.18-cp35-cp35m-win32.whl", hash = "sha256:cbe1324ef52ff26ccde2cb84b8593c8bf930069dfc06c1e616f1bfd4e47f48a3"},
{file = "SQLAlchemy-1.3.18-cp35-cp35m-win_amd64.whl", hash = "sha256:8fd452dc3d49b3cc54483e033de6c006c304432e6f84b74d7b2c68afa2569ae5"},
{file = "SQLAlchemy-1.3.18-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e89e0d9e106f8a9180a4ca92a6adde60c58b1b0299e1b43bd5e0312f535fbf33"},
{file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6ac2558631a81b85e7fb7a44e5035347938b0a73f5fdc27a8566777d0792a6a4"},
{file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:87fad64529cde4f1914a5b9c383628e1a8f9e3930304c09cf22c2ae118a1280e"},
{file = "SQLAlchemy-1.3.18-cp36-cp36m-win32.whl", hash = "sha256:e4624d7edb2576cd72bb83636cd71c8ce544d8e272f308bd80885056972ca299"},
{file = "SQLAlchemy-1.3.18-cp36-cp36m-win_amd64.whl", hash = "sha256:89494df7f93b1836cae210c42864b292f9b31eeabca4810193761990dc689cce"},
{file = "SQLAlchemy-1.3.18-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:716754d0b5490bdcf68e1e4925edc02ac07209883314ad01a137642ddb2056f1"},
{file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:50c4ee32f0e1581828843267d8de35c3298e86ceecd5e9017dc45788be70a864"},
{file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d98bc827a1293ae767c8f2f18be3bb5151fd37ddcd7da2a5f9581baeeb7a3fa1"},
{file = "SQLAlchemy-1.3.18-cp37-cp37m-win32.whl", hash = "sha256:0942a3a0df3f6131580eddd26d99071b48cfe5aaf3eab2783076fbc5a1c1882e"},
{file = "SQLAlchemy-1.3.18-cp37-cp37m-win_amd64.whl", hash = "sha256:16593fd748944726540cd20f7e83afec816c2ac96b082e26ae226e8f7e9688cf"},
{file = "SQLAlchemy-1.3.18-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c26f95e7609b821b5f08a72dab929baa0d685406b953efd7c89423a511d5c413"},
{file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:512a85c3c8c3995cc91af3e90f38f460da5d3cade8dc3a229c8e0879037547c9"},
{file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d05c4adae06bd0c7f696ae3ec8d993ed8ffcc4e11a76b1b35a5af8a099bd2284"},
{file = "SQLAlchemy-1.3.18-cp38-cp38-win32.whl", hash = "sha256:109581ccc8915001e8037b73c29590e78ce74be49ca0a3630a23831f9e3ed6c7"},
{file = "SQLAlchemy-1.3.18-cp38-cp38-win_amd64.whl", hash = "sha256:8619b86cb68b185a778635be5b3e6018623c0761dde4df2f112896424aa27bd8"},
{file = "SQLAlchemy-1.3.18.tar.gz", hash = "sha256:da2fb75f64792c1fc64c82313a00c728a7c301efe6a60b7a9fe35b16b4368ce7"},
]
toml = [
{file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
{file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
]
typed-ast = [
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
{file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"},
{file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"},
{file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"},
{file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"},
{file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"},
{file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"},
{file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"},
{file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"},
{file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"},
{file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"},
{file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"},
{file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"},
{file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"},
{file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"},
{file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"},
{file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"},
{file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"},
{file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"},
{file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
]
ujson = [
{file = "ujson-1.35.tar.gz", hash = "sha256:f66073e5506e91d204ab0c614a148d5aa938bdbf104751be66f8ad7a222f5f86"},
]
zipp = [
{file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"},
{file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"},
]

Просмотреть файл

@ -1,35 +1,63 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
[tool.poetry]
name = "CommA"
version = "0.1.0"
[build-system]
requires = ["setuptools >= 65"]
build-backend = "setuptools.build_meta"
[project]
name = "comma"
description = "Linux Commit Analyzer"
classifiers = [
"Programming Language :: Python :: 3",
"Development Status :: 5 - Production/Stable",
"Topic :: Software Development",
]
dependencies = [
"gitpython ~= 3.1.0",
"pyodbc ~= 4.0.30",
"python-Levenshtein ~= 0.12.0",
"fuzzywuzzy ~= 0.18.0",
"sqlalchemy ~= 1.3.13",
"openpyxl ~= 3.0.4",
]
dynamic = ["version"]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.8"
authors = [
"Ryan Feldman <ryfeldma@microsoft.com>",
"Abhishek Marathe <abmarath@microsoft.com>",
"Andrew Schwartzmeyer <andrew@schwartzmeyer.com>"]
license = "MIT"
{name = "Ryan Feldman", email = "ryfeldma@microsoft.com"},
{name = "Abhishek Marathe", email = "abmarath@microsoft.com"},
{name = "Andrew Schwartzmeyer", email = "andrew@schwartzmeyer.com"},
]
[tool.poetry.dependencies]
python = "^3.6"
gitpython = "^3.1.0"
pyodbc = "^4.0.30"
python-Levenshtein = "^0.12.0"
fuzzywuzzy = "^0.18.0"
sqlalchemy = "^1.3.13"
openpyxl = "^3.0.4"
[project.scripts]
comma = "comma.__main__:main"
[tool.poetry.dev-dependencies]
flake8 = "^3.7.9"
black = "^19.10b0"
isort = "^4.3.21"
flake8-bugbear = "^20.1.4"
python-language-server = {version = "^0.34.1", extras = ["flake8", "rope"]}
pyls-black = "^0.4.6"
pyls-isort = "^0.1.1"
[project.optional-dependencies]
flake8 = [
"flake8 ~= 3.7.9",
"flake8-bugbear ~= 20.1.4",
]
black = [
"black ~= 19.10b0",
]
isort = [
"isort ~= 4.3.21",
]
[project.urls]
homepage = "https://github.com/microsoft/Linux-CommA"
[tool.black]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
[tool.setuptools.packages.find]
include = ["comma*"]
namespaces = false
[tool.setuptools.dynamic]
version = {attr = "comma.__version__"}