diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4cc6bc2e..e97b3a77 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,64 +1,63 @@ -exclude: '^swh/web/tests/resources/' +exclude: "^swh/web/tests/resources/" repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.4.0 - hooks: - - id: trailing-whitespace - - id: check-json - - id: check-yaml - -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.3 - hooks: - - id: flake8 - -- repo: https://github.com/codespell-project/codespell - rev: v1.16.0 - hooks: - - id: codespell - exclude: > - (?x)^( - cypress/integration/directory.spec.js| - yarn.lock| - package.json - )$ - -- repo: local - hooks: - - id: mypy - name: mypy - entry: env DJANGO_SETTINGS_MODULE=swh.web.settings.development mypy - args: [swh] - pass_filenames: false - language: system - types: [python] - -- repo: local - hooks: - - id: eslint - name: eslint - entry: node_modules/.bin/eslint -c swh/web/assets/config/.eslintrc - language: system - types: [javascript] - -- repo: https://github.com/PyCQA/isort - rev: 5.5.2 - hooks: - - id: isort - -- repo: https://github.com/python/black - rev: 19.10b0 - hooks: - - id: black - + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.4.0 + hooks: + - id: trailing-whitespace + - id: check-json + - id: check-yaml + + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.3 + hooks: + - id: flake8 + + - repo: https://github.com/codespell-project/codespell + rev: v1.16.0 + hooks: + - id: codespell + exclude: > + (?x)^( + cypress/integration/directory.spec.js| + yarn.lock| + package.json + )$ + + - repo: local + hooks: + - id: mypy + name: mypy + entry: env DJANGO_SETTINGS_MODULE=swh.web.settings.development mypy + args: [swh] + pass_filenames: false + language: system + types: [python] + + - repo: local + hooks: + - id: eslint + name: eslint + entry: node_modules/.bin/eslint -c assets/config/.eslintrc + language: system + types: [javascript] + + - repo: https://github.com/PyCQA/isort + rev: 5.5.2 + hooks: + - id: isort + + - repo: https://github.com/python/black + rev: 19.10b0 + hooks: + - id: black # unfortunately, we are far from being able to enable this... # - repo: https://github.com/PyCQA/pydocstyle.git # rev: 4.0.0 # hooks: # - id: pydocstyle # name: pydocstyle # description: pydocstyle is a static analysis tool for checking compliance with Python docstring conventions. # entry: pydocstyle --convention=google # language: python # types: [python] diff --git a/MANIFEST.in b/MANIFEST.in index 9d93da96..1e16964a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,13 +1,13 @@ include pytest.ini include README.md include requirements*.txt include tox.ini include version.txt recursive-include swh py.typed -recursive-include swh/web/assets * +recursive-include assets * recursive-include swh/web/templates * recursive-include swh/web/tests/resources * include package.json include yarn.lock diff --git a/swh/web/assets/config/.bootstraprc b/assets/config/.bootstraprc similarity index 96% rename from swh/web/assets/config/.bootstraprc rename to assets/config/.bootstraprc index 0287a92a..5f7a5df6 100644 --- a/swh/web/assets/config/.bootstraprc +++ b/assets/config/.bootstraprc @@ -1,108 +1,108 @@ # Output debugging info # loglevel: debug # Major version of Bootstrap: 3 or 4 bootstrapVersion: 4 # Webpack loaders, order matters styleLoaders: - cache-loader - "css-loader?{\"sourceMap\": true}" - "postcss-loader?{\"sourceMap\": true}" - "sass-loader?{\"sourceMap\": true}" # Extract styles to stand-alone css file # Different settings for different environments can be used, # It depends on value of NODE_ENV environment variable # This param can also be set in webpack config: # entry: 'bootstrap-loader/extractStyles' extractStyles: true # env: # development: # extractStyles: false # production: # extractStyles: true # Customize Bootstrap variables that get imported before the original Bootstrap variables. # Thus, derived Bootstrap variables can depend on values from here. # See the Bootstrap _variables.scss file for examples of derived Bootstrap variables. # preBootstrapCustomizations: ./bootstrap-pre-customize.scss # This gets loaded after bootstrap/variables is loaded # Thus, you may customize Bootstrap variables # based on the values established in the Bootstrap _variables.scss file # #bootstrapCustomizations: ./bootstrap-customize.scss # Import your custom styles here # Usually this endpoint-file contains list of @imports of your application styles # # appStyles: ./path/to/your/app/styles/endpoint.scss -appStyles: ../../../../node_modules/admin-lte/build/scss/_adminlte.raw.scss +appStyles: ../../node_modules/admin-lte/build/scss/_adminlte.raw.scss ### Bootstrap styles styles: # Mixins mixins: true # Reset and dependencies print: true # Core CSS buttons: true code: true forms: true grid: true images: true reboot: true tables: true type: true # Components alert: true badge: true breadcrumb: true button-group: true card: true close: true custom-forms: true dropdown: true input-group: true jumbotron: true list-group: true media: true nav: true navbar: true pagination: true progress: true transitions: true # Components w/ JavaScript carousel: true modal: true popover: true tooltip: true # Utility classes utilities: true ### Bootstrap scripts scripts: alert: true button: true carousel: true collapse: true dropdown: true modal: true popover: true scrollspy: true tab: true tooltip: true util: true diff --git a/assets/config/.eslintignore b/assets/config/.eslintignore new file mode 100644 index 00000000..d94df78c --- /dev/null +++ b/assets/config/.eslintignore @@ -0,0 +1 @@ +assets/src/thirdparty/**/*.js diff --git a/swh/web/assets/config/.eslintrc b/assets/config/.eslintrc similarity index 100% rename from swh/web/assets/config/.eslintrc rename to assets/config/.eslintrc diff --git a/swh/web/assets/config/bootstrap-pre-customize.scss b/assets/config/bootstrap-pre-customize.scss similarity index 100% rename from swh/web/assets/config/bootstrap-pre-customize.scss rename to assets/config/bootstrap-pre-customize.scss diff --git a/swh/web/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js b/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js similarity index 100% rename from swh/web/assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js rename to assets/config/webpack-plugins/dump-highlightjs-languages-data-plugin.js diff --git a/swh/web/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js b/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js similarity index 100% rename from swh/web/assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js rename to assets/config/webpack-plugins/fix-swh-source-maps-webpack-plugin.js diff --git a/swh/web/assets/config/webpack-plugins/fix-webpack-stats-format-plugin.js b/assets/config/webpack-plugins/fix-webpack-stats-format-plugin.js similarity index 100% rename from swh/web/assets/config/webpack-plugins/fix-webpack-stats-format-plugin.js rename to assets/config/webpack-plugins/fix-webpack-stats-format-plugin.js diff --git a/swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/README.md b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/README.md similarity index 100% rename from swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/README.md rename to assets/config/webpack-plugins/generate-weblabels-webpack-plugin/README.md diff --git a/swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js similarity index 100% rename from swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js rename to assets/config/webpack-plugins/generate-weblabels-webpack-plugin/index.js diff --git a/swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/jslicenses.ejs b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/jslicenses.ejs similarity index 100% rename from swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/jslicenses.ejs rename to assets/config/webpack-plugins/generate-weblabels-webpack-plugin/jslicenses.ejs diff --git a/swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/plugin-options-schema.json b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/plugin-options-schema.json similarity index 100% rename from swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/plugin-options-schema.json rename to assets/config/webpack-plugins/generate-weblabels-webpack-plugin/plugin-options-schema.json diff --git a/swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/spdx-licenses-mapping.js b/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/spdx-licenses-mapping.js similarity index 100% rename from swh/web/assets/config/webpack-plugins/generate-weblabels-webpack-plugin/spdx-licenses-mapping.js rename to assets/config/webpack-plugins/generate-weblabels-webpack-plugin/spdx-licenses-mapping.js diff --git a/swh/web/assets/config/webpack.config.development.js b/assets/config/webpack.config.development.js similarity index 96% rename from swh/web/assets/config/webpack.config.development.js rename to assets/config/webpack.config.development.js index 60548795..7732aba6 100644 --- a/swh/web/assets/config/webpack.config.development.js +++ b/assets/config/webpack.config.development.js @@ -1,483 +1,483 @@ /** - * Copyright (C) 2018-2020 The Software Heritage developers + * Copyright (C) 2018-2021 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ // webpack configuration for compiling static assets in development mode // import required node modules and webpack plugins const chalk = require('chalk'); const fs = require('fs'); const path = require('path'); const webpack = require('webpack'); const BundleTracker = require('webpack-bundle-tracker'); const RobotstxtPlugin = require('robotstxt-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin; const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const FixSwhSourceMapsPlugin = require('./webpack-plugins/fix-swh-source-maps-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const GenerateWebLabelsPlugin = require('./webpack-plugins/generate-weblabels-webpack-plugin'); const ProgressBarPlugin = require('progress-bar-webpack-plugin'); const FixWebpackStatsFormatPlugin = require('./webpack-plugins/fix-webpack-stats-format-plugin'); const DumpHighlightjsLanguagesDataPlugin = require('./webpack-plugins/dump-highlightjs-languages-data-plugin'); // are we running webpack-dev-server ? const isDevServer = process.argv.find(v => v.includes('serve')) !== undefined; // webpack-dev-server configuration const devServerPort = 3000; const devServerPublicPath = 'http://localhost:' + devServerPort + '/static/'; // set publicPath according if we are using webpack-dev-server to serve // our assets or not const publicPath = isDevServer ? devServerPublicPath : '/static/'; -const nodeModules = path.resolve(__dirname, '../../../../node_modules/'); +const nodeModules = path.resolve(__dirname, '../../node_modules/'); // collect all bundles we want to produce with webpack var bundles = {}; const bundlesDir = path.join(__dirname, '../src/bundles'); fs.readdirSync(bundlesDir).forEach(file => { bundles[file] = ['bundles/' + file + '/index.js']; // workaround for https://github.com/webpack/webpack-dev-server/issues/2692 if (isDevServer) { bundles[file].unshift(`webpack-dev-server/client/index.js?http://localhost:${devServerPort}`); } }); // common loaders for css related assets (css, sass) let cssLoaders = [ MiniCssExtractPlugin.loader, { loader: 'cache-loader' }, { loader: 'css-loader', options: { sourceMap: !isDevServer } }, { loader: 'postcss-loader', options: { sourceMap: !isDevServer, postcssOptions: { plugins: [ // lint swh-web stylesheets ['stylelint', { 'config': { 'extends': 'stylelint-config-standard', 'rules': { 'indentation': 4, 'font-family-no-missing-generic-family-keyword': null, 'no-descending-specificity': null }, 'ignoreFiles': ['node_modules/**/*.css', - 'swh/web/assets/src/thirdparty/**/*.css'] + 'assets/src/thirdparty/**/*.css'] } }], // automatically add vendor prefixes to css rules 'autoprefixer', 'postcss-normalize', ['postcss-reporter', { clearReportedMessages: true }] ] } } } ]; // webpack development configuration module.exports = { // use caching to speedup incremental builds cache: { type: 'memory' }, // set mode to development mode: 'development', // workaround for https://github.com/webpack/webpack-dev-server/issues/2758 target: process.env.NODE_ENV === 'development' ? 'web' : 'browserslist', // use eval source maps when using webpack-dev-server for quick debugging, // otherwise generate source map files (more expensive) devtool: isDevServer ? 'eval' : 'source-map', // webpack-dev-server configuration devServer: { clientLogLevel: 'warning', port: devServerPort, publicPath: devServerPublicPath, // enable to serve static assets not managed by webpack contentBase: path.resolve('./'), // we do not use hot reloading here (as a framework like React needs to be used in order to fully benefit from that feature) // and prefer to fully reload the frontend application in the browser instead hot: false, inline: true, historyApiFallback: true, headers: { 'Access-Control-Allow-Origin': '*' }, compress: true, stats: 'errors-only', overlay: { warnings: true, errors: true }, // workaround for https://github.com/webpack/webpack-dev-server/issues/2692 injectClient: false }, // set entries to the bundles we want to produce entry: bundles, // assets output configuration output: { path: path.resolve('./static/'), filename: 'js/[name].[contenthash].js', chunkFilename: 'js/[name].[contenthash].js', publicPath: publicPath, // each bundle will be compiled as a umd module with its own namespace // in order to easily use them in django templates library: ['swh', '[name]'], libraryTarget: 'umd' }, // module resolving configuration resolve: { // alias pdfjs to its minified version alias: { 'pdfjs-dist': 'pdfjs-dist/build/pdf.min.js' }, // configure base paths for resolving modules with webpack modules: [ 'node_modules', path.resolve(__dirname, '../src') ] }, stats: 'errors-warnings', // module import configuration module: { rules: [ { // Preprocess all js files with eslint for consistent code style // and avoid bad js development practices. enforce: 'pre', test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'eslint-loader', options: { configFile: path.join(__dirname, '.eslintrc'), ignorePath: path.join(__dirname, '.eslintignore'), cache: true, emitWarning: true } }] }, { // Use babel-loader in order to use es6 syntax in js files // but also advanced js features like async/await syntax. // All code get transpiled to es5 in order to be executed // in a large majority of browsers. test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'cache-loader' }, { loader: 'babel-loader', options: { presets: [ // use env babel presets to benefit from es6 syntax ['@babel/preset-env', { // Do not transform es6 module syntax to another module type // in order to benefit from dead code elimination (aka tree shaking) // when running webpack in production mode 'loose': true, 'modules': false }] ], plugins: [ // use babel transform-runtime plugin in order to use aync/await syntax ['@babel/plugin-transform-runtime', { 'regenerator': true }], // use other babel plugins to benefit from advanced js features (es2017) '@babel/plugin-syntax-dynamic-import' ], env: { test: { plugins: ['istanbul'] } } } }] }, { test: /\.ejs$/, use: [{ loader: 'ejs-compiled-loader', options: { htmlmin: true, htmlminOptions: { removeComments: true } } }] }, // expose jquery to the global context as $ and jQuery when importing it { test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: { exposes: [ { globalName: '$', override: true }, { globalName: 'jQuery', override: true } ] } }] }, // expose highlightjs to the global context as hljs when importing it { test: require.resolve('highlight.js'), use: [{ loader: 'expose-loader', options: { exposes: { globalName: 'hljs', override: true } } }] }, { test: require.resolve('js-cookie'), use: [{ loader: 'expose-loader', options: { exposes: { globalName: 'Cookies', override: true } } }] }, // css import configuration: // - first process it with postcss // - then extract it to a dedicated file associated to each bundle { test: /\.css$/, use: cssLoaders }, // sass import configuration: // - generate css with sass-loader // - process it with postcss // - then extract it to a dedicated file associated to each bundle { test: /\.scss$/, use: cssLoaders.concat([ { loader: 'sass-loader', options: { sourceMap: !isDevServer } } ]) }, // web fonts import configuration { test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } }] }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } }] }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } }] }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } }] }, { test: /\.otf(\?v=\d+\.\d+\.\d+)?$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } }] }, { test: /\.png$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'img/thirdParty/' } }] } ], // tell webpack to not parse already minified files to speedup build process noParse: [path.resolve(nodeModules, 'pdfjs-dist/build/pdf.min.js'), path.resolve(nodeModules, 'mathjax/es5/tex-mml-chtml.js')] }, // webpack plugins plugins: [ // cleanup previously generated assets new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: ['**/*', '!xml', '!xml/*', '!img', '!img/*', '!img/logos', '!img/logos/*', '!img/icons', '!img/icons/*', '!json', '!json/*'] }), // needed in order to use django_webpack_loader new BundleTracker({ path: path.resolve('./static/'), filename: 'webpack-stats.json' }), // for generating the robots.txt file new RobotstxtPlugin({ policy: [{ userAgent: '*', disallow: '/api/' }] }), // for extracting all stylesheets in separate css files new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash].css', chunkFilename: 'css/[name].[contenthash].css' }), // fix generated asset sourcemaps to workaround a Firefox issue new FixSwhSourceMapsPlugin(), // define some global variables accessible from js code new webpack.DefinePlugin({ __STATIC__: JSON.stringify(publicPath) }), // needed in order to use bootstrap 4.x new webpack.ProvidePlugin({ Popper: ['popper.js', 'default'], Alert: 'exports-loader?Alert!bootstrap/js/dist/alert', Button: 'exports-loader?Button!bootstrap/js/dist/button', Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel', Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse', Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown', Modal: 'exports-loader?Modal!bootstrap/js/dist/modal', Popover: 'exports-loader?Popover!bootstrap/js/dist/popover', Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy', Tab: 'exports-loader?Tab!bootstrap/js/dist/tab', Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip', Util: 'exports-loader?Util!bootstrap/js/dist/util' }), // needed in order to use pdf.js new webpack.IgnorePlugin(/^\.\/pdf.worker.js$/), new CopyWebpackPlugin({ patterns: [ { from: path.resolve(nodeModules, 'pdfjs-dist/build/pdf.worker.min.js'), - to: path.resolve(__dirname, '../../../../static/js/') + to: path.resolve(__dirname, '../../static/js/') }, { from: path.resolve(nodeModules, 'mathjax/es5/output/chtml/fonts/woff-v2/**'), - to: path.resolve(__dirname, '../../../../static/fonts/[name].[ext]') + to: path.resolve(__dirname, '../../static/fonts/[name].[ext]') } ] }), new GenerateWebLabelsPlugin({ outputType: 'json', exclude: ['mini-css-extract-plugin', 'bootstrap-loader'], srcReplace: { './node_modules/pdfjs-dist/build/pdf.min.js': './node_modules/pdfjs-dist/build/pdf.js', './node_modules/admin-lte/dist/js/adminlte.min.js': './node_modules/admin-lte/dist/js/adminlte.js' }, licenseOverride: { - './swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': { + './assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': { 'spdxLicenseExpression': 'GPL-3.0', - 'licenseFilePath': './swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE' + 'licenseFilePath': './assets/src/thirdparty/jquery.tabSlideOut/LICENSE' } }, additionalScripts: Object.assign( { 'js/pdf.worker.min.js': [ { 'id': 'pdfjs-dist/build/pdf.worker.js', 'path': './node_modules/pdfjs-dist/build/pdf.worker.js', 'spdxLicenseExpression': 'Apache-2.0', 'licenseFilePath': './node_modules/pdfjs-dist/LICENSE' } ], '/jsreverse/': [ { 'id': 'jsreverse', 'path': '/jsreverse/', 'spdxLicenseExpression': 'AGPL-3.0-or-later', 'licenseFilePath': './LICENSE' } ], 'https://piwik.inria.fr/matomo.js': [ { 'id': 'matomo.js', 'path': 'https://github.com/matomo-org/matomo/blob/master/js/piwik.js', 'spdxLicenseExpression': 'BSD-3-Clause', 'licenseFilePath': 'https://github.com/matomo-org/matomo/blob/master/js/LICENSE.txt' } ] } ) }), new ProgressBarPlugin({ format: chalk.cyan.bold('webpack build of swh-web assets') + ' [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)', width: 50 }), new FixWebpackStatsFormatPlugin(), new DumpHighlightjsLanguagesDataPlugin() ], // webpack optimizations optimization: { // ensure the vendors bundle gets emitted in a single chunk splitChunks: { cacheGroups: { defaultVendors: { test: 'vendors', chunks: 'all', name: 'vendors', enforce: true } } } }, // disable webpack warnings about bundle sizes performance: { hints: false } }; diff --git a/swh/web/assets/config/webpack.config.production.js b/assets/config/webpack.config.production.js similarity index 100% rename from swh/web/assets/config/webpack.config.production.js rename to assets/config/webpack.config.production.js diff --git a/swh/web/assets/src/bundles/admin/deposit.js b/assets/src/bundles/admin/deposit.js similarity index 100% rename from swh/web/assets/src/bundles/admin/deposit.js rename to assets/src/bundles/admin/deposit.js diff --git a/swh/web/assets/src/bundles/admin/index.js b/assets/src/bundles/admin/index.js similarity index 100% rename from swh/web/assets/src/bundles/admin/index.js rename to assets/src/bundles/admin/index.js diff --git a/swh/web/assets/src/bundles/admin/origin-save.js b/assets/src/bundles/admin/origin-save.js similarity index 100% rename from swh/web/assets/src/bundles/admin/origin-save.js rename to assets/src/bundles/admin/origin-save.js diff --git a/swh/web/assets/src/bundles/auth/auth.css b/assets/src/bundles/auth/auth.css similarity index 100% rename from swh/web/assets/src/bundles/auth/auth.css rename to assets/src/bundles/auth/auth.css diff --git a/swh/web/assets/src/bundles/auth/index.js b/assets/src/bundles/auth/index.js similarity index 100% rename from swh/web/assets/src/bundles/auth/index.js rename to assets/src/bundles/auth/index.js diff --git a/swh/web/assets/src/bundles/browse/breadcrumbs.css b/assets/src/bundles/browse/breadcrumbs.css similarity index 100% rename from swh/web/assets/src/bundles/browse/breadcrumbs.css rename to assets/src/bundles/browse/breadcrumbs.css diff --git a/swh/web/assets/src/bundles/browse/browse-utils.js b/assets/src/bundles/browse/browse-utils.js similarity index 100% rename from swh/web/assets/src/bundles/browse/browse-utils.js rename to assets/src/bundles/browse/browse-utils.js diff --git a/swh/web/assets/src/bundles/browse/browse.css b/assets/src/bundles/browse/browse.css similarity index 100% rename from swh/web/assets/src/bundles/browse/browse.css rename to assets/src/bundles/browse/browse.css diff --git a/swh/web/assets/src/bundles/browse/content.css b/assets/src/bundles/browse/content.css similarity index 100% rename from swh/web/assets/src/bundles/browse/content.css rename to assets/src/bundles/browse/content.css diff --git a/swh/web/assets/src/bundles/browse/index.js b/assets/src/bundles/browse/index.js similarity index 100% rename from swh/web/assets/src/bundles/browse/index.js rename to assets/src/bundles/browse/index.js diff --git a/swh/web/assets/src/bundles/browse/origin-search.js b/assets/src/bundles/browse/origin-search.js similarity index 100% rename from swh/web/assets/src/bundles/browse/origin-search.js rename to assets/src/bundles/browse/origin-search.js diff --git a/swh/web/assets/src/bundles/browse/snapshot-navigation.css b/assets/src/bundles/browse/snapshot-navigation.css similarity index 100% rename from swh/web/assets/src/bundles/browse/snapshot-navigation.css rename to assets/src/bundles/browse/snapshot-navigation.css diff --git a/swh/web/assets/src/bundles/browse/snapshot-navigation.js b/assets/src/bundles/browse/snapshot-navigation.js similarity index 100% rename from swh/web/assets/src/bundles/browse/snapshot-navigation.js rename to assets/src/bundles/browse/snapshot-navigation.js diff --git a/swh/web/assets/src/bundles/browse/swhid-utils.js b/assets/src/bundles/browse/swhid-utils.js similarity index 100% rename from swh/web/assets/src/bundles/browse/swhid-utils.js rename to assets/src/bundles/browse/swhid-utils.js diff --git a/swh/web/assets/src/bundles/origin/index.js b/assets/src/bundles/origin/index.js similarity index 100% rename from swh/web/assets/src/bundles/origin/index.js rename to assets/src/bundles/origin/index.js diff --git a/swh/web/assets/src/bundles/origin/visits-calendar.js b/assets/src/bundles/origin/visits-calendar.js similarity index 100% rename from swh/web/assets/src/bundles/origin/visits-calendar.js rename to assets/src/bundles/origin/visits-calendar.js diff --git a/swh/web/assets/src/bundles/origin/visits-histogram.js b/assets/src/bundles/origin/visits-histogram.js similarity index 100% rename from swh/web/assets/src/bundles/origin/visits-histogram.js rename to assets/src/bundles/origin/visits-histogram.js diff --git a/swh/web/assets/src/bundles/origin/visits-reporting.css b/assets/src/bundles/origin/visits-reporting.css similarity index 100% rename from swh/web/assets/src/bundles/origin/visits-reporting.css rename to assets/src/bundles/origin/visits-reporting.css diff --git a/swh/web/assets/src/bundles/origin/visits-reporting.js b/assets/src/bundles/origin/visits-reporting.js similarity index 100% rename from swh/web/assets/src/bundles/origin/visits-reporting.js rename to assets/src/bundles/origin/visits-reporting.js diff --git a/swh/web/assets/src/bundles/revision/diff-panel.ejs b/assets/src/bundles/revision/diff-panel.ejs similarity index 100% rename from swh/web/assets/src/bundles/revision/diff-panel.ejs rename to assets/src/bundles/revision/diff-panel.ejs diff --git a/swh/web/assets/src/bundles/revision/diff-utils.js b/assets/src/bundles/revision/diff-utils.js similarity index 100% rename from swh/web/assets/src/bundles/revision/diff-utils.js rename to assets/src/bundles/revision/diff-utils.js diff --git a/swh/web/assets/src/bundles/revision/index.js b/assets/src/bundles/revision/index.js similarity index 100% rename from swh/web/assets/src/bundles/revision/index.js rename to assets/src/bundles/revision/index.js diff --git a/swh/web/assets/src/bundles/revision/log-utils.js b/assets/src/bundles/revision/log-utils.js similarity index 100% rename from swh/web/assets/src/bundles/revision/log-utils.js rename to assets/src/bundles/revision/log-utils.js diff --git a/swh/web/assets/src/bundles/revision/revision.css b/assets/src/bundles/revision/revision.css similarity index 100% rename from swh/web/assets/src/bundles/revision/revision.css rename to assets/src/bundles/revision/revision.css diff --git a/swh/web/assets/src/bundles/save/index.js b/assets/src/bundles/save/index.js similarity index 100% rename from swh/web/assets/src/bundles/save/index.js rename to assets/src/bundles/save/index.js diff --git a/swh/web/assets/src/bundles/vault/index.js b/assets/src/bundles/vault/index.js similarity index 100% rename from swh/web/assets/src/bundles/vault/index.js rename to assets/src/bundles/vault/index.js diff --git a/swh/web/assets/src/bundles/vault/vault-create-tasks.js b/assets/src/bundles/vault/vault-create-tasks.js similarity index 100% rename from swh/web/assets/src/bundles/vault/vault-create-tasks.js rename to assets/src/bundles/vault/vault-create-tasks.js diff --git a/swh/web/assets/src/bundles/vault/vault-table-row.ejs b/assets/src/bundles/vault/vault-table-row.ejs similarity index 100% rename from swh/web/assets/src/bundles/vault/vault-table-row.ejs rename to assets/src/bundles/vault/vault-table-row.ejs diff --git a/swh/web/assets/src/bundles/vault/vault-ui.js b/assets/src/bundles/vault/vault-ui.js similarity index 100% rename from swh/web/assets/src/bundles/vault/vault-ui.js rename to assets/src/bundles/vault/vault-ui.js diff --git a/swh/web/assets/src/bundles/vault/vault.css b/assets/src/bundles/vault/vault.css similarity index 100% rename from swh/web/assets/src/bundles/vault/vault.css rename to assets/src/bundles/vault/vault.css diff --git a/swh/web/assets/src/bundles/vendors/datatables.css b/assets/src/bundles/vendors/datatables.css similarity index 100% rename from swh/web/assets/src/bundles/vendors/datatables.css rename to assets/src/bundles/vendors/datatables.css diff --git a/swh/web/assets/src/bundles/vendors/elementsfrompoint-polyfill.js b/assets/src/bundles/vendors/elementsfrompoint-polyfill.js similarity index 100% rename from swh/web/assets/src/bundles/vendors/elementsfrompoint-polyfill.js rename to assets/src/bundles/vendors/elementsfrompoint-polyfill.js diff --git a/swh/web/assets/src/bundles/vendors/index.js b/assets/src/bundles/vendors/index.js similarity index 94% rename from swh/web/assets/src/bundles/vendors/index.js rename to assets/src/bundles/vendors/index.js index f7501a21..720e0eb1 100644 --- a/swh/web/assets/src/bundles/vendors/index.js +++ b/assets/src/bundles/vendors/index.js @@ -1,47 +1,47 @@ /** * Copyright (C) 2018-2019 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ // vendors bundles centralizing assets used in all swh-web applications // polyfills in order to use advanced js features (like Promise or fetch) // in browsers that do not support them import 'core-js/stable'; import 'regenerator-runtime/runtime'; import 'whatwg-fetch/dist/fetch.umd'; import './elementsfrompoint-polyfill'; // jquery and bootstrap import 'jquery'; -import 'bootstrap-loader/lib/bootstrap.loader?configFilePath=../../../swh/web/assets/config/.bootstraprc!bootstrap-loader/no-op.js'; +import 'bootstrap-loader/lib/bootstrap.loader?configFilePath=../../../assets/config/.bootstraprc!bootstrap-loader/no-op.js'; // admin-lte scripts import 'admin-lte'; // js-cookie import 'js-cookie'; // jquery datatables import 'datatables.net'; import 'datatables.net-responsive-bs4'; import 'datatables.net-bs4/css/dataTables.bootstrap4.css'; import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.css'; import './datatables.css'; // chosen-js import 'chosen-js'; import 'chosen-js/chosen.min.css'; // iframe-resizer import 'iframe-resizer'; // web fonts import 'typeface-alegreya'; import 'typeface-alegreya-sans'; import '@mdi/font/css/materialdesignicons.css'; // Monitoring import '@sentry/browser'; diff --git a/swh/web/assets/src/bundles/webapp/badges.js b/assets/src/bundles/webapp/badges.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/badges.js rename to assets/src/bundles/webapp/badges.js diff --git a/swh/web/assets/src/bundles/webapp/breadcrumbs.css b/assets/src/bundles/webapp/breadcrumbs.css similarity index 100% rename from swh/web/assets/src/bundles/webapp/breadcrumbs.css rename to assets/src/bundles/webapp/breadcrumbs.css diff --git a/swh/web/assets/src/bundles/webapp/code-highlighting.js b/assets/src/bundles/webapp/code-highlighting.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/code-highlighting.js rename to assets/src/bundles/webapp/code-highlighting.js diff --git a/swh/web/assets/src/bundles/webapp/history-counters.css b/assets/src/bundles/webapp/history-counters.css similarity index 100% rename from swh/web/assets/src/bundles/webapp/history-counters.css rename to assets/src/bundles/webapp/history-counters.css diff --git a/swh/web/assets/src/bundles/webapp/history-counters.js b/assets/src/bundles/webapp/history-counters.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/history-counters.js rename to assets/src/bundles/webapp/history-counters.js diff --git a/swh/web/assets/src/bundles/webapp/index.js b/assets/src/bundles/webapp/index.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/index.js rename to assets/src/bundles/webapp/index.js diff --git a/swh/web/assets/src/bundles/webapp/math-typesetting.js b/assets/src/bundles/webapp/math-typesetting.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/math-typesetting.js rename to assets/src/bundles/webapp/math-typesetting.js diff --git a/swh/web/assets/src/bundles/webapp/notebook-rendering.js b/assets/src/bundles/webapp/notebook-rendering.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/notebook-rendering.js rename to assets/src/bundles/webapp/notebook-rendering.js diff --git a/swh/web/assets/src/bundles/webapp/notebook.css b/assets/src/bundles/webapp/notebook.css similarity index 100% rename from swh/web/assets/src/bundles/webapp/notebook.css rename to assets/src/bundles/webapp/notebook.css diff --git a/swh/web/assets/src/bundles/webapp/pdf-rendering.js b/assets/src/bundles/webapp/pdf-rendering.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/pdf-rendering.js rename to assets/src/bundles/webapp/pdf-rendering.js diff --git a/swh/web/assets/src/bundles/webapp/readme-rendering.js b/assets/src/bundles/webapp/readme-rendering.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/readme-rendering.js rename to assets/src/bundles/webapp/readme-rendering.js diff --git a/swh/web/assets/src/bundles/webapp/sentry.js b/assets/src/bundles/webapp/sentry.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/sentry.js rename to assets/src/bundles/webapp/sentry.js diff --git a/swh/web/assets/src/bundles/webapp/status-widget.css b/assets/src/bundles/webapp/status-widget.css similarity index 100% rename from swh/web/assets/src/bundles/webapp/status-widget.css rename to assets/src/bundles/webapp/status-widget.css diff --git a/swh/web/assets/src/bundles/webapp/status-widget.js b/assets/src/bundles/webapp/status-widget.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/status-widget.js rename to assets/src/bundles/webapp/status-widget.js diff --git a/swh/web/assets/src/bundles/webapp/webapp-utils.js b/assets/src/bundles/webapp/webapp-utils.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/webapp-utils.js rename to assets/src/bundles/webapp/webapp-utils.js diff --git a/swh/web/assets/src/bundles/webapp/webapp.css b/assets/src/bundles/webapp/webapp.css similarity index 100% rename from swh/web/assets/src/bundles/webapp/webapp.css rename to assets/src/bundles/webapp/webapp.css diff --git a/swh/web/assets/src/bundles/webapp/xss-filtering.js b/assets/src/bundles/webapp/xss-filtering.js similarity index 100% rename from swh/web/assets/src/bundles/webapp/xss-filtering.js rename to assets/src/bundles/webapp/xss-filtering.js diff --git a/swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE b/assets/src/thirdparty/jquery.tabSlideOut/LICENSE similarity index 100% rename from swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE rename to assets/src/thirdparty/jquery.tabSlideOut/LICENSE diff --git a/swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.css b/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.css similarity index 100% rename from swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.css rename to assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.css diff --git a/swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js b/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js similarity index 100% rename from swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js rename to assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js diff --git a/swh/web/assets/src/utils/constants.js b/assets/src/utils/constants.js similarity index 100% rename from swh/web/assets/src/utils/constants.js rename to assets/src/utils/constants.js diff --git a/swh/web/assets/src/utils/d3.js b/assets/src/utils/d3.js similarity index 100% rename from swh/web/assets/src/utils/d3.js rename to assets/src/utils/d3.js diff --git a/swh/web/assets/src/utils/functions.js b/assets/src/utils/functions.js similarity index 100% rename from swh/web/assets/src/utils/functions.js rename to assets/src/utils/functions.js diff --git a/swh/web/assets/src/utils/highlightjs.css b/assets/src/utils/highlightjs.css similarity index 100% rename from swh/web/assets/src/utils/highlightjs.css rename to assets/src/utils/highlightjs.css diff --git a/swh/web/assets/src/utils/highlightjs.js b/assets/src/utils/highlightjs.js similarity index 100% rename from swh/web/assets/src/utils/highlightjs.js rename to assets/src/utils/highlightjs.js diff --git a/swh/web/assets/src/utils/mathjax.js b/assets/src/utils/mathjax.js similarity index 100% rename from swh/web/assets/src/utils/mathjax.js rename to assets/src/utils/mathjax.js diff --git a/swh/web/assets/src/utils/org.css b/assets/src/utils/org.css similarity index 100% rename from swh/web/assets/src/utils/org.css rename to assets/src/utils/org.css diff --git a/swh/web/assets/src/utils/org.js b/assets/src/utils/org.js similarity index 100% rename from swh/web/assets/src/utils/org.js rename to assets/src/utils/org.js diff --git a/swh/web/assets/src/utils/showdown.css b/assets/src/utils/showdown.css similarity index 100% rename from swh/web/assets/src/utils/showdown.css rename to assets/src/utils/showdown.css diff --git a/swh/web/assets/src/utils/showdown.js b/assets/src/utils/showdown.js similarity index 100% rename from swh/web/assets/src/utils/showdown.js rename to assets/src/utils/showdown.js diff --git a/package.json b/package.json index 4fe41a6e..d3836dd8 100644 --- a/package.json +++ b/package.json @@ -1,135 +1,135 @@ { "name": "swh-web", "version": "0.0.289", "description": "Static assets management for swh-web", "scripts": { - "build-dev": "NODE_ENV=development webpack --config ./swh/web/assets/config/webpack.config.development.js --color", - "build-test": "NODE_ENV=test webpack --config ./swh/web/assets/config/webpack.config.development.js --color", - "start-dev": "NODE_ENV=development nodemon --watch swh/web/api --watch swh/web/browse --watch swh/web/templates --watch swh/web/common --watch swh/web/settings --watch swh/web/assets/config --ext py,html,js --exec \"webpack serve --config ./swh/web/assets/config/webpack.config.development.js --color\"", - "build": "NODE_ENV=production webpack --config ./swh/web/assets/config/webpack.config.production.js --color", + "build-dev": "NODE_ENV=development webpack --config assets/config/webpack.config.development.js --color", + "build-test": "NODE_ENV=test webpack --config assets/config/webpack.config.development.js --color", + "start-dev": "NODE_ENV=development nodemon --watch swh/web/api --watch swh/web/browse --watch swh/web/templates --watch swh/web/common --watch swh/web/settings --watch assets/config --ext py,html,js --exec \"webpack serve --config assets/config/webpack.config.development.js --color\"", + "build": "NODE_ENV=production webpack --config assets/config/webpack.config.production.js --color", "mochawesome": "mochawesome-merge cypress/mochawesome/results/*.json > cypress/mochawesome/mochawesome.json && marge -o cypress/mochawesome/report cypress/mochawesome/mochawesome.json", - "eslint": "eslint -c swh/web/assets/config/.eslintrc --fix swh/web/assets/** cypress/integration/** cypress/plugins/** cypress/support/**", + "eslint": "eslint -c assets/config/.eslintrc --fix assets/** cypress/integration/** cypress/plugins/** cypress/support/**", "preinstall": "npm -v || (SWH_WEB=$PWD && cd /tmp && yarn add npm && cd node_modules/npm && yarn link && cd $SWH_WEB && yarn link npm)", "nyc-report": "nyc report --reporter=lcov" }, "repository": { "type": "git", "url": "https://forge.softwareheritage.org/source/swh-web" }, "author": "The Software Heritage developers", "license": "AGPL-3.0-or-later", "dependencies": { "@babel/runtime-corejs3": "^7.13.10", "@mdi/font": "^5.9.55", "@sentry/browser": "^6.2.3", "admin-lte": "^3.1.0", "ansi_up": "^5.0.0", "bootstrap": "^4.6.0", "chosen-js": "^1.8.7", "clipboard": "^2.0.8", "core-js": "^3.9.1", "d3": "^6.6.2", "datatables.net-responsive-bs4": "^2.2.7", "dompurify": "^2.2.7", "highlight.js": "^10.7.1", "highlightjs-line-numbers.js": "^2.8.0", "html-encoder-decoder": "^1.3.9", "iframe-resizer": "^4.3.1", "jquery": "^3.6.0", "js-cookie": "^2.2.1", "js-year-calendar": "^1.0.2", "mathjax": "^3.1.2", "notebookjs": "^0.6.4", "object-fit-images": "^3.2.4", "org": "^0.2.0", "pdfjs-dist": "^2.6.347", "popper.js": "^1.16.1", "showdown": "^1.9.1", "typeface-alegreya": "^1.1.13", "typeface-alegreya-sans": "^1.1.13", "waypoints": "^4.0.1", "whatwg-fetch": "^3.6.2" }, "devDependencies": { "@babel/core": "^7.13.14", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-runtime": "^7.13.10", "@babel/preset-env": "^7.13.12", "@cypress/code-coverage": "^3.9.4", "autoprefixer": "^10.2.5", "axios": "^0.21.1", "babel-eslint": "^10.1.0", "babel-loader": "^8.2.2", "babel-plugin-istanbul": "^6.0.0", "bootstrap-loader": "^3.0.4", "cache-loader": "^4.1.0", "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^8.1.0", "css-loader": "^5.2.0", "cypress": "^6.8.0", "cypress-multi-reporters": "^1.4.0", "ejs": "^3.1.6", "ejs-compiled-loader": "^3.0.0", "eslint": "^7.23.0", "eslint-loader": "^4.0.2", "eslint-plugin-chai-friendly": "^0.6.0", "eslint-plugin-cypress": "^2.11.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "eslint-plugin-standard": "^5.0.0", "exports-loader": "^2.0.0", "expose-loader": "^2.0.0", "file-loader": "^6.2.0", "imports-loader": "^2.0.0", "istanbul-lib-coverage": "^3.0.0", "json-stable-stringify": "^1.0.1", "mini-css-extract-plugin": "^1.4.0", "mocha": "^8.3.2", "mocha-junit-reporter": "^2.0.0", "mochawesome": "^6.2.2", "mochawesome-merge": "^4.2.0", "mochawesome-report-generator": "^5.2.0", "node-sass": "^5.0.0", "nodemon": "^2.0.7", "nyc": "^15.1.0", "optimize-css-assets-webpack-plugin": "^5.0.4", "postcss": "^8.2.8", "postcss-loader": "^5.2.0", "postcss-normalize": "^9.0.0", "postcss-reporter": "^7.0.2", "progress-bar-webpack-plugin": "^2.1.0", "resolve-url-loader": "^3.1.2", "robotstxt-webpack-plugin": "^7.0.0", "sass-loader": "^11.0.1", "schema-utils": "^3.0.0", "script-loader": "^0.7.2", "spdx-expression-parse": "^3.0.1", "style-loader": "^2.0.0", "stylelint": "^13.12.0", "stylelint-config-standard": "^21.0.0", "terser-webpack-plugin": "^5.1.1", "url-loader": "^4.1.1", "webpack": "^5.28.0", "webpack-bundle-tracker": "^1.0.0-alpha.1", "webpack-cli": "^4.6.0", "webpack-dev-server": "^3.11.2" }, "resolutions": { "jquery": "^3.6.0" }, "browserslist": [ "cover 99.5%", "not dead" ], "nyc": { "report-dir": "cypress/coverage", "exclude": [ - "swh/web/assets/src/bundles/vendors/index.js", - "swh/web/assets/src/thirdparty/**/*.js" + "assets/src/bundles/vendors/index.js", + "assets/src/thirdparty/**/*.js" ] }, "engines": { "node": ">=8.9.0" } } \ No newline at end of file diff --git a/setup.py b/setup.py index f7e5a2bb..4a9033c1 100755 --- a/setup.py +++ b/setup.py @@ -1,76 +1,77 @@ #!/usr/bin/env python3 # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License v3 or later # See top-level LICENSE file for more information from io import open import os from os import path from setuptools import find_packages, setup here = path.abspath(path.dirname(__file__)) # Get the long description from the README file with open(path.join(here, "README.md"), encoding="utf-8") as f: long_description = f.read() def parse_requirements(name=None): if name: reqf = "requirements-%s.txt" % name else: reqf = "requirements.txt" requirements = [] if not path.exists(reqf): return requirements with open(reqf) as f: for line in f.readlines(): line = line.strip() if not line or line.startswith("#"): continue requirements.append(line) return requirements # package generated static assets as module data files data_files = [] -for root, _, files in os.walk("static/"): - root_files = [os.path.join(root, i) for i in files] - data_files.append((os.path.join("share/swh/web", root), root_files)) +for folder in ("static/", "assets/"): + for root, _, files in os.walk(folder): + root_files = [os.path.join(root, i) for i in files] + data_files.append((os.path.join("share/swh/web", root), root_files)) setup( name="swh.web", description="Software Heritage Web UI", long_description=long_description, long_description_content_type="text/markdown", python_requires=">=3.7", author="Software Heritage developers", author_email="swh-devel@inria.fr", url="https://forge.softwareheritage.org/diffusion/DWUI/", packages=find_packages(), scripts=[], install_requires=parse_requirements() + parse_requirements("swh"), setup_requires=["setuptools-scm"], use_scm_version=True, extras_require={"testing": parse_requirements("test")}, include_package_data=True, classifiers=[ "Programming Language :: Python :: 3", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", # noqa "Operating System :: OS Independent", "Development Status :: 5 - Production/Stable", "Framework :: Django", ], project_urls={ "Bug Reports": "https://forge.softwareheritage.org/maniphest", "Funding": "https://www.softwareheritage.org/donate", "Source": "https://forge.softwareheritage.org/source/swh-web", "Documentation": "https://docs.softwareheritage.org/devel/swh-web/", }, data_files=data_files, ) diff --git a/swh/web/assets/config/.eslintignore b/swh/web/assets/config/.eslintignore deleted file mode 100644 index 0b94c932..00000000 --- a/swh/web/assets/config/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -swh/web/assets/src/thirdparty/**/*.js diff --git a/swh/web/tests/conftest.py b/swh/web/tests/conftest.py index 0bb1510e..00b3f7cf 100644 --- a/swh/web/tests/conftest.py +++ b/swh/web/tests/conftest.py @@ -1,376 +1,385 @@ # Copyright (C) 2018-2021 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import json import os import shutil from subprocess import PIPE, run import sys from typing import Any, Dict, List, Optional from hypothesis import HealthCheck from hypothesis import __version_info__ as hypothesis_version from hypothesis import settings import pytest from django.core.cache import cache from rest_framework.test import APIClient, APIRequestFactory from swh.model.hashutil import ALGORITHMS, hash_to_bytes from swh.storage.algos.origin import origin_get_latest_visit_status from swh.storage.algos.snapshot import snapshot_get_all_branches, snapshot_get_latest from swh.web.auth.utils import OIDC_SWH_WEB_CLIENT_ID from swh.web.common import converters from swh.web.common.typing import OriginVisitInfo from swh.web.config import get_config from swh.web.tests.data import get_tests_data, override_storages pytest_plugins = ["swh.auth.pytest_plugin"] # Used to skip some tests ctags_json_missing = ( shutil.which("ctags") is None or b"+json" not in run(["ctags", "--version"], stdout=PIPE).stdout ) fossology_missing = shutil.which("nomossa") is None # Register some hypothesis profiles settings.register_profile("default", settings()) suppress_health_check = [HealthCheck.too_slow, HealthCheck.filter_too_much] if hypothesis_version >= (5, 49): suppress_health_check.append(HealthCheck.function_scoped_fixture) settings.register_profile( "swh-web", settings(deadline=None, suppress_health_check=suppress_health_check,), ) settings.register_profile( "swh-web-fast", settings( deadline=None, max_examples=1, suppress_health_check=suppress_health_check, ), ) def pytest_configure(config): # Use fast hypothesis profile by default if none has been # explicitly specified in pytest option if config.getoption("--hypothesis-profile") is None: settings.load_profile("swh-web-fast") + # Small hack in order to be able to run the unit tests # without static assets generated by webpack. # Those assets are not really needed for the Python tests # but the django templates will fail to load due to missing # generated file webpack-stats.json describing the js and css # files to include. # So generate a dummy webpack-stats.json file to overcome # that issue. test_dir = os.path.dirname(__file__) # location of the static folder when running tests through tox - static_dir = os.path.join(sys.prefix, "share/swh/web/static") + data_dir = os.path.join(sys.prefix, "share/swh/web") + static_dir = os.path.join(data_dir, "static") if not os.path.exists(static_dir): # location of the static folder when running tests locally with pytest static_dir = os.path.join(test_dir, "../../../static") + webpack_stats = os.path.join(static_dir, "webpack-stats.json") if os.path.exists(webpack_stats): return - bundles_dir = os.path.join(test_dir, "../assets/src/bundles") - _, dirs, _ = next(os.walk(bundles_dir)) + + bundles_dir = os.path.join(test_dir, "../../../assets/src/bundles") + if not os.path.exists(bundles_dir): + # location of the bundles folder when running tests with tox + bundles_dir = os.path.join(data_dir, "assets/src/bundles") + + _, bundles, _ = next(os.walk(bundles_dir)) + mock_webpack_stats = {"status": "done", "publicPath": "/static", "chunks": {}} - for bundle in dirs: + for bundle in bundles: asset = "js/%s.js" % bundle mock_webpack_stats["chunks"][bundle] = [ { "name": asset, "publicPath": "/static/%s" % asset, "path": os.path.join(static_dir, asset), } ] with open(webpack_stats, "w") as outfile: json.dump(mock_webpack_stats, outfile) # Clear Django cache before each test @pytest.fixture(autouse=True) def django_cache_cleared(): cache.clear() # Alias rf fixture from pytest-django @pytest.fixture def request_factory(rf): return rf # Fixture to get test client from Django REST Framework @pytest.fixture(scope="module") def api_client(): return APIClient() # Fixture to get API request factory from Django REST Framework @pytest.fixture(scope="module") def api_request_factory(): return APIRequestFactory() # Initialize tests data @pytest.fixture(scope="session", autouse=True) def tests_data(): data = get_tests_data(reset=True) # Update swh-web configuration to use the in-memory storages # instantiated in the tests.data module override_storages(data["storage"], data["idx_storage"], data["search"]) return data # Fixture to manipulate data from a sample archive used in the tests @pytest.fixture(scope="session") def archive_data(tests_data): return _ArchiveData(tests_data) # Fixture to manipulate indexer data from a sample archive used in the tests @pytest.fixture(scope="session") def indexer_data(tests_data): return _IndexerData(tests_data) # Custom data directory for requests_mock @pytest.fixture def datadir(): return os.path.join(os.path.abspath(os.path.dirname(__file__)), "resources") class _ArchiveData: """ Helper class to manage data from a sample test archive. It is initialized with a reference to an in-memory storage containing raw tests data. It is basically a proxy to Storage interface but it overrides some methods to retrieve those tests data in a json serializable format in order to ease tests implementation. """ def __init__(self, tests_data): self.storage = tests_data["storage"] def __getattr__(self, key): if key == "storage": raise AttributeError(key) # Forward calls to non overridden Storage methods to wrapped # storage instance return getattr(self.storage, key) def content_find(self, content: Dict[str, Any]) -> Dict[str, Any]: cnt_ids_bytes = { algo_hash: hash_to_bytes(content[algo_hash]) for algo_hash in ALGORITHMS if content.get(algo_hash) } cnt = self.storage.content_find(cnt_ids_bytes) return converters.from_content(cnt[0].to_dict()) if cnt else cnt def content_get(self, cnt_id: str) -> Dict[str, Any]: cnt_id_bytes = hash_to_bytes(cnt_id) content = self.storage.content_get([cnt_id_bytes])[0] if content: content_d = content.to_dict() content_d.pop("ctime", None) else: content_d = None return converters.from_swh( content_d, hashess={"sha1", "sha1_git", "sha256", "blake2s256"} ) def content_get_data(self, cnt_id: str) -> Optional[Dict[str, Any]]: cnt_id_bytes = hash_to_bytes(cnt_id) cnt_data = self.storage.content_get_data(cnt_id_bytes) if cnt_data is None: return None return converters.from_content({"data": cnt_data, "sha1": cnt_id_bytes}) def directory_get(self, dir_id): return {"id": dir_id, "content": self.directory_ls(dir_id)} def directory_ls(self, dir_id): cnt_id_bytes = hash_to_bytes(dir_id) dir_content = map( converters.from_directory_entry, self.storage.directory_ls(cnt_id_bytes) ) return list(dir_content) def release_get(self, rel_id: str) -> Optional[Dict[str, Any]]: rel_id_bytes = hash_to_bytes(rel_id) rel_data = self.storage.release_get([rel_id_bytes])[0] return converters.from_release(rel_data) if rel_data else None def revision_get(self, rev_id: str) -> Optional[Dict[str, Any]]: rev_id_bytes = hash_to_bytes(rev_id) rev_data = self.storage.revision_get([rev_id_bytes])[0] return converters.from_revision(rev_data) if rev_data else None def revision_log(self, rev_id, limit=None): rev_id_bytes = hash_to_bytes(rev_id) return list( map( converters.from_revision, self.storage.revision_log([rev_id_bytes], limit=limit), ) ) def snapshot_get_latest(self, origin_url): snp = snapshot_get_latest(self.storage, origin_url) return converters.from_snapshot(snp.to_dict()) def origin_get(self, origin_urls): origins = self.storage.origin_get(origin_urls) return [converters.from_origin(o.to_dict()) for o in origins] def origin_visit_get(self, origin_url): next_page_token = None visits = [] while True: visit_page = self.storage.origin_visit_get( origin_url, page_token=next_page_token ) next_page_token = visit_page.next_page_token for visit in visit_page.results: visit_status = self.storage.origin_visit_status_get_latest( origin_url, visit.visit ) visits.append( converters.from_origin_visit( {**visit_status.to_dict(), "type": visit.type} ) ) if not next_page_token: break return visits def origin_visit_get_by(self, origin_url: str, visit_id: int) -> OriginVisitInfo: visit = self.storage.origin_visit_get_by(origin_url, visit_id) assert visit is not None visit_status = self.storage.origin_visit_status_get_latest(origin_url, visit_id) assert visit_status is not None return converters.from_origin_visit( {**visit_status.to_dict(), "type": visit.type} ) def origin_visit_status_get_latest( self, origin_url, type: Optional[str] = None, allowed_statuses: Optional[List[str]] = None, require_snapshot: bool = False, ): visit_status = origin_get_latest_visit_status( self.storage, origin_url, type=type, allowed_statuses=allowed_statuses, require_snapshot=require_snapshot, ) return ( converters.from_origin_visit(visit_status.to_dict()) if visit_status else None ) def snapshot_get(self, snapshot_id): snp = snapshot_get_all_branches(self.storage, hash_to_bytes(snapshot_id)) return converters.from_snapshot(snp.to_dict()) def snapshot_get_branches( self, snapshot_id, branches_from="", branches_count=1000, target_types=None ): partial_branches = self.storage.snapshot_get_branches( hash_to_bytes(snapshot_id), branches_from.encode(), branches_count, target_types, ) return converters.from_partial_branches(partial_branches) def snapshot_get_head(self, snapshot): if snapshot["branches"]["HEAD"]["target_type"] == "alias": target = snapshot["branches"]["HEAD"]["target"] head = snapshot["branches"][target]["target"] else: head = snapshot["branches"]["HEAD"]["target"] return head def snapshot_count_branches(self, snapshot_id): counts = dict.fromkeys(("alias", "release", "revision"), 0) counts.update(self.storage.snapshot_count_branches(hash_to_bytes(snapshot_id))) counts.pop(None, None) return counts class _IndexerData: """ Helper class to manage indexer tests data It is initialized with a reference to an in-memory indexer storage containing raw tests data. It also defines class methods to retrieve those tests data in a json serializable format in order to ease tests implementation. """ def __init__(self, tests_data): self.idx_storage = tests_data["idx_storage"] self.mimetype_indexer = tests_data["mimetype_indexer"] self.license_indexer = tests_data["license_indexer"] self.ctags_indexer = tests_data["ctags_indexer"] def content_add_mimetype(self, cnt_id): self.mimetype_indexer.run([hash_to_bytes(cnt_id)]) def content_get_mimetype(self, cnt_id): mimetype = self.idx_storage.content_mimetype_get([hash_to_bytes(cnt_id)])[ 0 ].to_dict() return converters.from_filetype(mimetype) def content_add_license(self, cnt_id): self.license_indexer.run([hash_to_bytes(cnt_id)]) def content_get_license(self, cnt_id): cnt_id_bytes = hash_to_bytes(cnt_id) licenses = self.idx_storage.content_fossology_license_get([cnt_id_bytes]) for license in licenses: yield converters.from_swh(license.to_dict(), hashess={"id"}) def content_add_ctags(self, cnt_id): self.ctags_indexer.run([hash_to_bytes(cnt_id)]) def content_get_ctags(self, cnt_id): cnt_id_bytes = hash_to_bytes(cnt_id) ctags = self.idx_storage.content_ctags_get([cnt_id_bytes]) for ctag in ctags: yield converters.from_swh(ctag, hashess={"id"}) @pytest.fixture def keycloak_oidc(keycloak_oidc, mocker): keycloak_config = get_config()["keycloak"] keycloak_oidc.server_url = keycloak_config["server_url"] keycloak_oidc.realm_name = keycloak_config["realm_name"] keycloak_oidc.client_id = OIDC_SWH_WEB_CLIENT_ID keycloak_oidc_client = mocker.patch("swh.web.auth.views.keycloak_oidc_client") keycloak_oidc_client.return_value = keycloak_oidc return keycloak_oidc