Git Product home page Git Product logo

upm's Introduction

UPM

GoDoc Run on Repl.it

UPM is the Universal Package Manager. It allows you to manage packages for any (supported) programming language through the same interface following the principle of least astonishment. At Repl.it, we use UPM to provide deep package manager integration for many different programming languages using the same infrastructure.

UPM does not implement package management itself. Instead, it runs a package manager for you. The value added is:

  • you don't have to figure out whether to use Pip or Pipenv or Poetry to manage your Python packages or wade into the Cabal-versus-Stack holy war in Haskell-land
  • you don't have to puzzle out why pip search flask doesn't return Flask in the search results
  • you don't have to debug Bundler silently dropping your command-line options if you don't specify them in the right (undocumented) order
  • you don't have to think about why the developers of NPM and Yarn decided to implement two completely different and mutually incompatible behaviors for list --depth=0, neither of which is exactly what you want
  • you don't have to investigate what format the Yarn lockfile is in (turns out: almost YAML, but not quite)
  • et cetera (I could go on all day)

In other words, UPM eliminates the need to remember a huge collection of language-specific package manager quirks and weirdness, and adds a few nifty extra features like dependency guessing and machine-parseable specfile and lockfile listing.

Supported languages

  • Core: upm add, upm remove, upm lock, upm install, upm list
  • Index: upm search, upm info
  • Guess: upm guess
core index guess
python-python3-pip yes yes yes
python-python3-poetry yes yes yes
nodejs-yarn yes yes yes
nodejs-pnpm yes yes yes
nodejs-npm yes yes yes
ruby-bundler yes yes
elisp-cask yes yes yes
dart-pub.dev yes yes
rlang yes yes
java yes yes
rust yes yes
dotnet yes yes
php yes yes

Installation

You have many options. UPM is a single binary with no dependencies, so you can install it anywhere. Tarballs are available on the releases page. Read on for instructions on installing via a package manager.

macOS

Available on Homebrew in a custom tap.

$ brew install replit/tap/upm

Debian-based Linux

.deb packages are available on the releases page.

RPM-based Linux

.rpm packages are available on the releases page.

Arch Linux

Soon to be available on the Arch User Repository. Right now, you can clone this repository and install with makepkg using the PKGBUILD in packaging/aur.

Windows

Available on Scoop in a custom bucket.

$ scoop bucket add replit https://github.com/replit/scoop-bucket.git
$ scoop install upm

Snappy

Soon to be available on the Snap Store. Right now, .snap packages are available on the releases page.

Docker

You can try out UPM right away in a Docker image based on Ubuntu that has all the supported languages and package managers already installed.

$ docker run -it --rm replco/upm

Additional tags are also available. replco/upm:full is the same as the above, while replco/upm:light just has the UPM binary installed to /usr/local/bin and none of the languages or package managers installed. If you want to run a specific tagged release, rather than the latest development snapshot, use e.g. replco/upm:1.0, replco/upm:1.0-full, or replco/upm:1.0-light.

Quick start

Let's create a new Python project:

$ mkdir ~/python
$ cd ~/python

We'll start by adding Flask as a dependency. UPM will handle setting up the project for us:

$ upm -l python add flask
--> python3 -m poetry init --no-interaction

This command will guide you through creating your pyproject.toml config.


--> python3 -m poetry add flask
Creating virtualenv python-py3.7 in /root/.cache/pypoetry/virtualenvs
Using version ^1.1 for flask

Updating dependencies
Resolving dependencies... (0.6s)

Writing lock file


Package operations: 6 installs, 0 updates, 0 removals

  - Installing markupsafe (1.1.1)
  - Installing click (7.0)
  - Installing itsdangerous (1.1.0)
  - Installing jinja2 (2.10.1)
  - Installing werkzeug (0.15.4)
  - Installing flask (1.1.1)

UPM operates on a specfile and lockfile for each project. The specfile says what your project's dependencies are in a human-readable format, while the lockfile specifies exact versions for everything, including transitive dependencies. For Python, the specfile is pyproject.toml and the lockfile is poetry.lock:

$ ls
poetry.lock  pyproject.toml

We don't have to read them ourselves, because UPM can handle that. Notice that UPM is now aware that our project uses Python, because of the files that were created:

$ upm list
name    spec
-----   ----
flask   ^1.1

$ upm list -a
name           version
------------   -------
click          7.0
flask          1.1.1
itsdangerous   1.1.0
jinja2         2.10.1
markupsafe     1.1.1
werkzeug       0.15.4

Let's search for another dependency to add:

$ upm search nose
--> python3 -c '<secret sauce>' nose
Name                Description                                                              Version
-----------------   ----------------------------------------------------------------------   -------
nose                nose extends unittest to make testing easier                             1.3.7
nose-detecthttp     A nose plugin to detect tests making http calls.                         1.1.0
nose-picker         nose plugin that picks a subset of your unit tests                       0.5.5
nose-progressive    A testrunner with a progress bar and smarter tracebacks                  1.5.2
nose-unittest       UNKNOWN                                                                  0.1.1
nose-blockage       Raise errors when communicating outside of tests                         0.1.2
nose-watcher        A nose plugin to watch for changes within the local directory.           0.1.3
nose-bisect         A Nose plugin which allows bisection of test failures.                   0.1.0
nose-printlog       Print log to console in nose tests                                       0.2.0
nose-json           A JSON report plugin for Nose.                                           0.2.4
nose-faulthandler   Nose plugin. Activates faulthandler module for test runs.                0.1
nose-knows                                                                                   0.2
nose-pagerduty      PagerDuty alert plugin for nose                                          0.2.0
nose-logpertest     Logging nose plugin to create log per test                               0.0.1
nose-bleed          A progressive coverage plugin for Nose.                                  0.5.1
nose-numpyseterr    Nose plugin to set how floating-point errors are handled by numpy        0.1
nose-skipreq        nose plugin that will skip Google API RequestError exceptions.           2.0
nose-selecttests    Specify whitelist of keywords for tests to be run by nose                0.5
nose-pacman         A testrunner with a pacman progress bar                                  0.1.0
nose-switch         Add special switches in code, based on options set when running tests.   0.1.5

We can get more information about a package like this:

$ upm info nose
--> python3 -c '<secret sauce>' nose
Name:          nose
Description:   nose extends unittest to make testing easier
Version:       1.3.7
Homepage:      http://readthedocs.org/docs/nose/
Author:        Jason Pellerin <[email protected]>
License:       GNU LGPL

For piping into other programs, the search and info commands can also output JSON:

$ upm info nose --format=json | jq
--> python3 -c '<secret sauce>' nose
{
  "name": "nose",
  "description": "nose extends unittest to make testing easier",
  "version": "1.3.7",
  "homepageURL": "http://readthedocs.org/docs/nose/",
  "author": "Jason Pellerin <[email protected]>",
  "license": "GNU LGPL"
}

UPM can also look at your project's source code and guess what packages need to be installed. We use this on Repl.it to help developers get started faster. To see it in action, we'll need some source code:

$ git clone https://github.com/replit/play.git ~/play
$ cd ~/play
$ upm add --guess
--> python3 -c '<secret sauce>' '<secret sauce>'
--> python3 -m poetry init --no-interaction

This command will guide you through creating your pyproject.toml config.


--> python3 -m poetry add pygame pymunk setuptools
Creating virtualenv play-py3.7 in /root/.cache/pypoetry/virtualenvs
Using version ^1.9 for pygame
Using version ^5.5 for pymunk
Using version ^41.0 for setuptools

Updating dependencies
Resolving dependencies... (1.4s)

Writing lock file


Package operations: 4 installs, 0 updates, 0 removals

  - Installing pycparser (2.19)
  - Installing cffi (1.12.3)
  - Installing pygame (1.9.6)
  - Installing pymunk (5.5.0)

You can also just get the list of guessed dependencies, if you want. The -a flag lists all guessed dependencies, even the ones already added to the specfile:

$ upm guess -a
pygame
pymunk
setuptools

All of this might seem a bit too simple to justify a new tool, but the real power of UPM is that it works exactly the same for every programming language:

$ upm -l nodejs info express
Name:          express
Description:   Fast, unopinionated, minimalist web framework
Version:       4.17.1
Homepage:      http://expressjs.com/
Source code:   git+https://github.com/expressjs/express.git
Bug tracker:   https://github.com/expressjs/express/issues
Author:        TJ Holowaychuk <[email protected]>
License:       MIT

$ upm -l ruby info jekyll
--> ruby -e '<secret sauce>' jekyll
Name:            jekyll
Description:     Jekyll is a simple, blog aware, static site generator.
Version:         3.8.6
Homepage:        https://github.com/jekyll/jekyll
Documentation:   http://jekyllrb.com
Source code:     https://github.com/jekyll/jekyll
Bug tracker:     https://github.com/jekyll/jekyll/issues
Author:          Tom Preston-Werner
License:         MIT
Dependencies:    addressable, colorator, em-websocket, i18n, jekyll-sass-converter, jekyll-watch, kramdown, liquid, mercenary, pathutil, rouge, safe_yaml

$ upm -l elisp info elnode
--> emacs -Q --batch --eval '<secret sauce>' /tmp/elpa552971126 info elnode
Name:           elnode
Description:    The Emacs webserver.
Version:        20190702.1509
Dependencies:   web, dash, noflet, s, creole, fakir, db, kv

That includes adding and removing packages, listing the specfile and lockfile, searching package indices, and guessing project dependencies. UPM knows all the best practices for each language so that you don't have to!

Usage

Explore the command-line interface at your leisure:

$ upm --help
Usage:
  upm [command]

Available Commands:
  which-language   Query language autodetection
  list-languages   List supported languages
  search           Search for packages online
  info             Show package information from online registry
  add              Add packages to the specfile
  remove           Remove packages from the specfile
  lock             Generate the lockfile from the specfile
  install          Install packages from the lockfile
  list             List packages from the specfile (or lockfile)
  guess            Guess what packages are needed by your project
  show-specfile    Print the filename of the specfile
  show-lockfile    Print the filename of the lockfile
  show-package-dir Print the directory where packages are installed
  help             Help about any command

Flags:
  -h, --help                       display command-line usage
      --ignored-packages strings   packages to ignore when guessing (comma-separated)
  -l, --lang string                specify project language(s) manually
  -q, --quiet                      don't show what commands are being run
  -v, --version                    display command version

Use "upm [command] --help" for more information about a command.

Here are useful things to know that aren't obvious:

  • Language detection: Your project's language is autodetected by the files in the current directory. This can be overridden either partially or completely by specifying a value for the -l option. You can see the available languages by running upm list-languages. In addition to a full language (e.g. python-python3-poetry), you can specify something simpler (e.g. python, python3, python2, poetry, python-poetry). In that case, UPM will examine all of the matching languages and pick whichever one it thinks is best. You can experiment with this logic by providing the -l option to upm which-language.
  • Information flow: Conceptually, information about packages flows one way in UPM: add/remove -> specfile -> lockfile -> installed packages. You run upm add and upm remove, which modifies the specfile, and then the lockfile is automatically generated from the specfile, and then packages are automatically installed or uninstalled according to the lockfile. Just running upm add or upm remove will automatically perform all of these steps. Skipping steps is unfortunately not supported, because few package managers support that. You can however run only later steps in the pipeline by means of the upm lock and upm install commands.
  • Caching: UPM maintains a simple JSON cache in the .upm subdirectory of your project, in order to improve performance. This is used to (1) skip generating the lockfile from the specfile if the specfile hasn't changed since last time; (2) skip reinstalling packages from the lockfile if the lockfile hasn't changed since last time; and (3) skip doing a full analysis of your code on upm guess if your imports haven't actually changed since last time (according to a quick regexp search). To reset the cache, you can delete that directory. However, this shouldn't be necessary very often, because you can use the --force-lock and --force-install options to upm add, upm remove, upm lock, and upm install (it is just --force for upm install due to lack of ambiguity) in order to ignore the cache for cases (1) and (2).

Environment variables respected

  • UPM_PROJECT: path to top-level directory containing project files. UPM uses this as its working directory. Defaults to the first parent directory containing a directory entry named .upm (like Git searches for .git), or the current directory if .upm is not found.
  • UPM_PYTHON2: if nonempty, use instead of python2 when invoking Python 2.
  • UPM_PYTHON3: if nonempty, use instead of python3 when invoking Python 3.
  • UPM_SILENCE_SUBROUTINES: if nonempty, then enable -q when running commands that are not directly related to the operation the user requested (e.g. if running upm add, enable -q when reading the specfile to check which packages are already added).
  • UPM_STORE: path of file used to store the JSON cache file, relative or absolute. Defaults to .upm/store.json.

Dependencies

UPM itself has no dependencies. It is a single statically-linked binary. However, if you wish to actually use it to manage packages for a language, then the relevant language package manager needs to be installed, as follows:

All of these dependencies are already installed in the replco/upm:full Docker image.

Contributing

$ make help
usage:
  make upm       Build the UPM binary
  make dev       Run a shell with UPM source code and all package managers inside Docker
  make light     Build a Docker image with just the UPM binary
  make full      Build a Docker image with the UPM binary and all package managers
  make doc       Open Godoc in web browser
  make deploy    Publish UPM snapshot Docker images to Docker Hub
  make pkgbuild  Update and test PKGBUILD
  make clean     Remove build artifacts
  make help      Show this message

To build UPM, run make upm (or just make), the built binary can be found in ./cmd/upm/upm. To remove build artifacts, run make clean.

Using Replit (simplest)

You can develop UPM on Replit. Simply click on this link and the repo will start cloning into a Repl.

Once you're in your new Repl, you can hit run to build a new binary (or make in shell). You can create a test folder and use the binary and test your changes. For example say you made a change to the nodejs-npm language and want to test it, you would hit run and do the following:

$ mkdir testnpm
$ cd testnpm
$ npm init -y
$ ../cmd/upm/upm add left-pad -l nodejs-npm

Using Docker

You can use Docker to avoid needing to install the package managers that UPM drives. To do this, run make dev. This will build an image and launch a shell inside the container with the UPM source directory on your computer synced with the filesystem inside the container. The same Makefile targets are available, and UPM is added to the $PATH automatically. You only need to restart the shell if you edit the Dockerfile or the scripts used by the Dockerfile. Aliases available inside the shell:

  • l: ls -lAhF
  • mt: create temporary directory and cd to it (convenient for switching to a new "project" context)
  • u: build UPM binary if source code has been modified, then run with given arguments
  • ub: same as u, but force rebuilding binary (may be useful if you previously built outside the Docker container)

To build a Docker image which has only the UPM binary, for embedding in other images, run make light. The image will be tagged as upm:light. Alternatively, to build a Docker image which has the binary and all the package managers, but not the UPM source code, run make full. The image will be tagged as upm:full. These two images are automatically built and deployed to Docker Hub when a commit is merged to master.

UPM does not currently have any tests; however, we plan to fix this.

Deployment

Whenever a commit is merged to master, snapshot Docker images are built and pushed to Docker Hub by CircleCI. Whenever a tagged release (e.g. v1.0) is pushed to GitHub, the following happens:

  • Release Docker images are tagged and pushed to Docker Hub.
  • The changelog is parsed and published as a GitHub Release with the following assets:
    • source code (.zip and .tar.gz)
    • binary (.tar.gz; darwin, freebsd, linux, and windows; 386 and amd64)
    • Debian package (.deb; 386 and amd64)
    • RPM package (.rpm; 386 and amd64)
    • Snappy package (.snap; 386 and amd64)
    • checksums (.txt)
  • The Repl.it Homebrew tap is updated.
  • The Repl.it Scoop bucket is updated.

Once you push a release and it passes CI, the following must be done manually:

  • Edit packaging/aur/PKGBUILD with the new version and run make pkgbuild to update and test the AUR package. Then push a new commit. (Once we are allowed to publish to AUR, you should also push packaging/aur there.)

upm's People

Contributors

airportyh avatar alanvf avatar amasad avatar blast-hardcheese avatar cbrewster avatar cdmistman avatar chwoda1 avatar dependabot[bot] avatar hackermondev avatar lhchavez avatar masad-frost avatar minivera avatar miselin avatar mit-mit avatar navteniev avatar raxod502 avatar ryantm avatar sergeichestakov avatar zabot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

upm's Issues

Provide info as to why different providers are not available

An extension to #2.

Currently, we have

dstewart$ upm list-languages
python3-poetry
python3-pip  (unavailable)
bun
nodejs-npm
nodejs-pnpm
nodejs-yarn  (unavailable)
ruby-bundler
elisp-cask  (unavailable)
dart-pub  (unavailable)
java-maven  (unavailable)
rlang  (unavailable)
dotnet  (unavailable)
rust  (unavailable)
php-composer  (unavailable)

what would be preferable would be

python3-poetry
python3-pip  (unavailable, see: https://pip.pypa.io/en/stable/installation/)
bun
nodejs-npm
nodejs-pnpm
nodejs-yarn  (unavailable, see: https://yarnpkg.com/getting-started/install)
ruby-bundler
elisp-cask  (unavailable, see: https://cask.readthedocs.io/en/latest/guide/installation.html)

or even better,

dstewart$ upm list-languages
python3-poetry
bun
nodejs-npm
nodejs-pnpm
ruby-bundler

Unavailable
---
python3-pip  (see: https://pip.pypa.io/en/stable/installation/)
nodejs-yarn  (see: https://yarnpkg.com/getting-started/install)
elisp-cask   (emacs: ✓, cask: ✗, see: https://cask.readthedocs.io/en/latest/guide/installation.html)

...

Can't handle packages for nodejs with alias

I have some packages like:

  ...,
  "dependencies": {
    "@nuxtjs/auth": "^4.9.1",
    "@nuxtjs/axios": "^5.12.0",
    "@nuxtjs/proxy": "^2.0.1",
    "@nuxtjs/pwa": "^3.0.0-beta.20",
  }

upm read them as:

some-project on  master [!?] is 📦 v1.0.0 on 🐳 v19.03.13 
➜ upm add --guess     
--> yarn add vue-i18n nuxt_plugin_axios_cde3cfa4 vuex nuxt_plugin_workbox_0fb939ca moment vue-router deepcopy defu vue vuetify nuxt_plugin_pluginmain_11d296d2 vue-meta nuxt_plugin_plugin_412891d6 unfetch nuxt_plugin_cookieuniversalnuxt_c544c854 nuxt_plugin_plugin_2c7c6a2c nuxt_plugin_icons_61876082 js-cookie axios nuxt_plugin_meta_7ad8c670 dotenv node-fetch vue-no-ssr @/utils vue-client-only is-https nuxt_plugin_plugin_3ab90918 cookie-universal cookie nuxt_plugin_notification_1685ae90 nuxt_plugin_pluginrouting_5d43c5d8

So this all fail with error:

yarn add v1.22.10
[1/4] Resolving packages...
error An unexpected error occurred: "https://registry.yarnpkg.com/nuxt_plugin_axios_cde3cfa4: Not found".

Because upm incorrectly read package names.

I guess this unexpected behavior.

P.S.
If you haven't hand to handle this issue, you can describe solution a bit, I am impressed with your project and will be happy to contribute.

Can't build golang package

Hi,

When trying to build the package using go install, I have this error: go: github.com/replit/upm/internal/statik: no matching versions for query "upgrade"

This is what I do to build it:

  1. git clone https://github.com/replit/upm.git
  2. cd upm
  3. go mod tidy
  4. go install -v ./cmd/upm

This is where I get the error

Any ideas ?

Doesn't work with Poetry binary installed directly

On Manjaro Linux:

% upm -l python add numpy                                                             
--> python3 -m poetry init --no-interaction
/usr/bin/python3: No module named poetry
exit status 1

This is because when Poetry is installed via the system package manager, it isn't available as a Python module; you need to go through the executable /usr/bin/poetry.

Add support for Clojure

From what i understand prybar-clojure uses clojure-cli tools and deps.edn, would upm support clojure librarie either using deps.edn or lein(using project.clj). I see that as my primary limiting factor while using clojure on repl.it unlike python/dart where I can import libraries with ease.

PNPM Support?

There is already support for Yarn and NPM, I think PNPM would be attainable. I would be happy to implement it myself if I knew where to start.

Exits with Status 9009

Running on Windows 10 with Python3

Trying to run any upm commands that utilize poetry result in a 9009. I have installed it from Scoop.

Is there a way to get verbose output?

Maven

Support also Maven?

python: Blacklist pies2overrides on python3

The pies2overrides package is only intended to be installed on python 2; installing it on python 3 will break things because it conflicts with packages in the standard library. UPM sometimes suggests this package, apparently because it doesn't know that the module builtins comes from the standard library instead of a pypi module.

Repro instructions:

On repl.it, create a new python3 repl. Type import builtins in main.py and click run. It will try to automatically install pies2overrides and go into an infinite loop (demo repl: https://repl.it/@bdarnell/UnevenAshamedUnderstanding#main.py)

Suggested resolution:

Add pies2overrides to a blacklist, never to be installed automatically (at least not on python 3. It's potentially useful for python 2, although I'm not sure it's the sort of thing that would be good to auto-install). Or maintain an up-to-date list of packages in the standard library and don't recommend third-party packages that provide the same names.

Support for Rust Crates via Cargo

After the announcement, I started researching how easy could be to support Rust packages (with Crates.io/cargo) in this project.

I think the integration should be in general trivial, but cargo requires to manually modify Cargo.toml in order to add or remove packages (as opposed to doing it via a specific CLI subcommand like in npm, poetry, ...).

Is there any good way to support this? Have someone else thought about this?

Increase verbosity in CMD outputs

For a few commands like upm guess I think there should be more verbosity in the resulting output, or an option flag to enable that manually. If upm guess doesn't find any packages (or whatever language-specific equivalent) in a project, the command will pass silently without any say-so!

I'd open a PR and do it myself, but I don't know much Go 😅

Add support for Haskell (Stack)

I'm working on haskell(stack) support on my repo.

Stack works differently than most other package management tools. Instead of giving a version to each dependency, Stack uses curated sets to packages that work well together as "resolvers". packages not on stack can be specified with versions.

Stack therefore uses a minimum of two files: one for configuration and version specification of non-stackage packages and one for listing all dependencies. Additionally, one file for storing sha256 sums of the packages to ensure safe builds.
a reference

I've listed the first file (stack.yaml) as lockfile and second (project.cabal) as the specfile. While they are close, they do not fit into the traditional idea of lockfiles and specfiles. Therefore, ListSpecFile will return package names only without version and ListLockFile will return some packages names along with version. What side-effects will this have?

Also, I need to know how repl.it's package manager UI uses the upm add command: with or without the version specification provided by PkgInfo.

Poetry installing wrong package

On PyPi, there are 2 packages called glm: glm and PyGLM. The former is now unmaintained and is (I believe) a json parser, whereas the other is an OpenGL mathematics library. I am developing a library which depends on the latter, but it is imported with import glm. However, upm guess will automatically resolve the dependencies by installing glm which then screws up PyGLM. Is there a way to turn off upm guess from running automatically when I run my repl?

How to handle special dependencies like development or extra

Most projects have development dependencies which are only required if you want to work on the library itself (e.g. testing frameworks).
Additionally, in Python packages, there's the concept of "extra dependencies" which are not required for the core functionality but allow for some extra functionality.

How can these different dependency flavors by handled with UPM?

Backend api 'Remove' function signature

This is probably a generic golang question. The signature of 'Remove' field of a backend api is:

field Remove func(map[PkgName]bool)

All the bool values in the map passed are set to true. Why is this hook being passed a map instead of an array?

Add support for Golang

Hi! Love the project and statically analyzing python code for imports would be SUPER valuable for our project - is there any chance you're thinking about creating a 'upm guess' golang package?

Bundle install is throwing error in case of ruby!

I was trying to compile a jekyll based ruby static site on replit when i run into the issue below. I am unable to run

bundle install 

and getting error below. I am attaching all of the console here :

~/jekyll-website$ bundle install
Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Using bundler 2.4.10
Using concurrent-ruby 1.2.2
Using forwardable-extended 2.6.0
Using rb-fsevent 0.11.2
Using rexml 3.2.6
Using http_parser.rb 0.8.0
Using mercenary 0.3.6
Using rouge 3.30.0
Using safe_yaml 1.0.5
Using i18n 1.14.1
Using kramdown 2.4.0
Using pathutil 0.16.2
Using liquid 4.0.4
Using colorator 1.1.0
Using public_suffix 5.0.4
Using addressable 2.8.6
Installing eventmachine 1.2.7 with native extensions
Installing ffi 1.16.3 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:
/home/runner/jekyll-website/.bundle/ruby/3.2.0/gems/eventmachine-1.2.7/ext
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/bin/ruby extconf.rb
checking for -lcrypto... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
--ruby=/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/bin/$(RUBY_BASE_NAME)
    --with-ssl-dir
    --without-ssl-dir
    --with-ssl-include
    --without-ssl-include=${ssl-dir}/include
    --with-ssl-lib
    --without-ssl-lib=${ssl-dir}/lib
    --with-openssl-dir
    --without-openssl-dir
    --with-openssl-include
    --without-openssl-include=${openssl-dir}/include
    --with-openssl-lib
    --without-openssl-lib=${openssl-dir}/lib
    --with-openssl-config
    --without-openssl-config
    --with-pkg-config
    --without-pkg-config
    --with-crypto-dir
    --without-crypto-dir
    --with-crypto-include
    --without-crypto-include=${crypto-dir}/include
    --with-crypto-lib
    --without-crypto-lib=${crypto-dir}/lib
    --with-cryptolib
    --without-cryptolib
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:490:in
`try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.

from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:583:in
`try_link0'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:601:in
`try_link'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:819:in
`try_func'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:1062:in
`block in have_library'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:989:in
`block in checking_for'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:354:in
`block (2 levels) in postpone'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:324:in
`open'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:354:in
`block in postpone'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:324:in
`open'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:350:in
`postpone'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:988:in
`checking_for'
from
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/mkmf.rb:1057:in
`have_library'
    from extconf.rb:8:in `block in check_libs'
    from extconf.rb:8:in `all?'
    from extconf.rb:8:in `check_libs'
    from extconf.rb:95:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can
be found here:

/home/runner/jekyll-website/.bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/eventmachine-1.2.7/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in
/home/runner/jekyll-website/.bundle/ruby/3.2.0/gems/eventmachine-1.2.7 for
inspection.
Results logged to
/home/runner/jekyll-website/.bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/eventmachine-1.2.7/gem_make.out

/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/builder.rb:120:in
`run'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/ext_conf_builder.rb:28:in
`build'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/builder.rb:188:in
`build_extension'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/builder.rb:222:in
`block in build_extensions'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/builder.rb:219:in
`each'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/ext/builder.rb:219:in
`build_extensions'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/rubygems/installer.rb:839:in
`build_extensions'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/rubygems_gem_installer.rb:72:in
`build_extensions'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/rubygems_gem_installer.rb:28:in
`install'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/source/rubygems.rb:200:in
`install'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/installer/gem_installer.rb:54:in
`install'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/installer/gem_installer.rb:16:in
`install_from_spec'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/installer/parallel_installer.rb:156:in
`do_install'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/installer/parallel_installer.rb:147:in
`block in worker_pool'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/worker.rb:62:in
`apply_func'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/worker.rb:57:in
`block in process_queue'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/worker.rb:54:in
`loop'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/worker.rb:54:in
`process_queue'
/nix/store/cym9m41909x2fihq7xrzv5vivjjf60gj-ruby-3.2.2/lib/ruby/3.2.0/bundler/worker.rb:90:in
`block (2 levels) in create_threads'

An error occurred while installing eventmachine (1.2.7), and Bundler
cannot continue.

In Gemfile:
  no-style-please was resolved to 0.4.7, which depends on
    jekyll-feed was resolved to 0.15.1, which depends on
      jekyll was resolved to 3.9.3, which depends on
        em-websocket was resolved to 0.5.3, which depends on
          eventmachine
Screenshot 2023-12-19 at 12 46 37

Switch to statically analyzed Ruby Guess

Ruby guess is broken:

$ upm guess
--> ruby -e '<secret sauce>'
<internal:/nix/store/d3mglw6m4ikwf7aw0rxz3abj5cv176ha-ruby-3.1.4/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- parser/current (LoadError)
    from <internal:/nix/store/d3mglw6m4ikwf7aw0rxz3abj5cv176ha-ruby-3.1.4/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from -e:1:in `<main>'
exit status 1

Imports incorrect modules in Python when Poetry already has correct module

So some packages, such as py-ulid, have a different name from the imported module, in this case import ulid, or as usually done, from ulid import ULID.

If you import with Repl.it, then the first time you run it everything works fine. If you close and open again, the next time it tries to import the module ulid, which has a completely different interface and doesn't have a ULID class to import, and now no longer runs as ulid, which python attempts to resolve against rather than py-ulid (and doesn't keep checking after the failure), doesn't have a ULID to import.

Namely, UPM needs to either check against the existing packages that have been added, seeing if they are applicable, or it needs to check whether the packages it tried to include actually satisfy the interface of the program (even just flagging up that the ulid package doesn't have ULID while py-ulid, which is already in the Poetry file, does).

This isn't really the fault of UPM, since Python is the one not checking for these when it is trying to resolve the imports, however this needs to be worked around in order to be Universal until (if ever) Python fixes this, especially for versions that do not have the fixed version should it ever happen.

python package guesser should understand direct vs transitive dependencies

the map (https://github.com/replit/upm/blob/master/internal/backends/python/pypi_packages.json) we're using for python's package guesser includes modules from transitive dependencies in the same set as those directly provided. We should build a better mapping which includes both transitive and direct modules.

Transitive modules should only be used to determine which modules are already satisfied by the existing packages. When guessing we should only use modules directly from the package.

When a packager backend is not available it should say so

$ upm -l python add flask
--> python3 -m poetry init --no-interaction
/usr/local/opt/python/bin/python3.7: No module named poetry
exit status 1

It should probably say something more descriptive and preferably instruct the user on how to install it.

For an even better UX when I list-languages it should say what's available and what's not.
e.g.

$ upm list-languages
python-python3-poetry (unavailable)
python-python2-poetry
nodejs-yarn
nodejs-npm
ruby-bundler (unavailable)
elisp-cask

Stop using deprecated bundler options in ruby

A deprecation warning is printed when the rails ruby package is added:

--> bundle init
Writing new Gemfile to /home/runner/RotatingTediousServers/Gemfile
--> bundle add --skip-install rails
Fetching gem metadata from https://rubygems.org/.............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies....
--> bundle config --parseable path
--> bundle install --clean --path .bundle
[DEPRECATED] The `--clean` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set clean 'true'`, and stop using this flag
[DEPRECATED] The `--path` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set path '.bundle'`, and stop using this flag

Add support for Nim (Nimble)

I'm just starting out with Nim, so I'm not yet familiar enough with the tooling to contribute anything to this project, however it would be good to support this tool as well.

Repository export

please support the chance to export a target repositori (i.e. NPM), to restore in other installation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.